xair-api 2.3.1__tar.gz → 2.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {xair_api-2.3.1 → xair_api-2.3.2}/PKG-INFO +11 -2
- {xair_api-2.3.1 → xair_api-2.3.2}/README.md +10 -1
- {xair_api-2.3.1 → xair_api-2.3.2}/pyproject.toml +16 -2
- xair_api-2.3.2/xair_api/errors.py +14 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/util.py +29 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/xair.py +18 -12
- xair_api-2.3.1/xair_api/errors.py +0 -2
- {xair_api-2.3.1 → xair_api-2.3.2}/LICENSE +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/__init__.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/adapter.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/bus.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/config.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/dca.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/fx.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/kinds.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/lr.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/meta.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/rtn.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/shared.py +0 -0
- {xair_api-2.3.1 → xair_api-2.3.2}/xair_api/strip.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: xair-api
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.2
|
|
4
4
|
Summary: Remote control Behringer X-Air | Midas MR mixers through OSC
|
|
5
5
|
Home-page: https://github.com/onyx-and-iris/xair-api-python
|
|
6
6
|
License: MIT
|
|
@@ -73,7 +73,7 @@ if __name__ == "__main__":
|
|
|
73
73
|
main()
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
#### `xair_api.connect(kind_id, ip=ip, delay=
|
|
76
|
+
#### `xair_api.connect(kind_id, ip=ip, delay=0.02, connect_timeout=2)`
|
|
77
77
|
|
|
78
78
|
Currently the following devices are supported:
|
|
79
79
|
|
|
@@ -90,6 +90,7 @@ The following keyword arguments may be passed:
|
|
|
90
90
|
- `port`: mixer port, defaults to 10023 for x32 and 10024 for xair
|
|
91
91
|
- `delay`: a delay between each command (applies to the getters). Defaults to 20ms.
|
|
92
92
|
- a note about delay, stability may rely on network connection. For wired connections the delay can be safely reduced.
|
|
93
|
+
- `connect_timeout`: amount of time to wait for a validated connection. Defaults to 2s.
|
|
93
94
|
|
|
94
95
|
## API
|
|
95
96
|
|
|
@@ -335,6 +336,14 @@ for example:
|
|
|
335
336
|
print(mixer.query("/ch/01/mix/on"))
|
|
336
337
|
```
|
|
337
338
|
|
|
339
|
+
### Errors
|
|
340
|
+
|
|
341
|
+
- `errors.XAirRemoteError`: Base error class for XAIR Remote.
|
|
342
|
+
- `errors.XAirRemoteConnectionTimeoutError`:Exception raised when a connection attempt times out.
|
|
343
|
+
- The following attributes are available:
|
|
344
|
+
- `ip`: IP of the mixer.
|
|
345
|
+
- `port`: Port of the mixer.
|
|
346
|
+
|
|
338
347
|
### `Tests`
|
|
339
348
|
|
|
340
349
|
Unplug any expensive equipment before running tests.
|
|
@@ -55,7 +55,7 @@ if __name__ == "__main__":
|
|
|
55
55
|
main()
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
#### `xair_api.connect(kind_id, ip=ip, delay=
|
|
58
|
+
#### `xair_api.connect(kind_id, ip=ip, delay=0.02, connect_timeout=2)`
|
|
59
59
|
|
|
60
60
|
Currently the following devices are supported:
|
|
61
61
|
|
|
@@ -72,6 +72,7 @@ The following keyword arguments may be passed:
|
|
|
72
72
|
- `port`: mixer port, defaults to 10023 for x32 and 10024 for xair
|
|
73
73
|
- `delay`: a delay between each command (applies to the getters). Defaults to 20ms.
|
|
74
74
|
- a note about delay, stability may rely on network connection. For wired connections the delay can be safely reduced.
|
|
75
|
+
- `connect_timeout`: amount of time to wait for a validated connection. Defaults to 2s.
|
|
75
76
|
|
|
76
77
|
## API
|
|
77
78
|
|
|
@@ -317,6 +318,14 @@ for example:
|
|
|
317
318
|
print(mixer.query("/ch/01/mix/on"))
|
|
318
319
|
```
|
|
319
320
|
|
|
321
|
+
### Errors
|
|
322
|
+
|
|
323
|
+
- `errors.XAirRemoteError`: Base error class for XAIR Remote.
|
|
324
|
+
- `errors.XAirRemoteConnectionTimeoutError`:Exception raised when a connection attempt times out.
|
|
325
|
+
- The following attributes are available:
|
|
326
|
+
- `ip`: IP of the mixer.
|
|
327
|
+
- `port`: Port of the mixer.
|
|
328
|
+
|
|
320
329
|
### `Tests`
|
|
321
330
|
|
|
322
331
|
Unplug any expensive equipment before running tests.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "xair-api"
|
|
3
|
-
version = "2.3.
|
|
3
|
+
version = "2.3.2"
|
|
4
4
|
description = "Remote control Behringer X-Air | Midas MR mixers through OSC"
|
|
5
5
|
authors = ["onyx-and-iris <code@onyxandiris.online>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -13,10 +13,11 @@ python-osc = "^1.8.0"
|
|
|
13
13
|
tomli = { version = "^2.0.1", python = "<3.11" }
|
|
14
14
|
|
|
15
15
|
[tool.poetry.group.dev.dependencies]
|
|
16
|
-
pytest = "^7.
|
|
16
|
+
pytest = "^7.4.4"
|
|
17
17
|
pytest-randomly = "^3.12.0"
|
|
18
18
|
black = "^22.6.0"
|
|
19
19
|
isort = "^5.10.1"
|
|
20
|
+
tox = "^4.12.1"
|
|
20
21
|
|
|
21
22
|
[build-system]
|
|
22
23
|
requires = ["poetry-core>=1.0.0"]
|
|
@@ -27,3 +28,16 @@ obs = "scripts:ex_obs"
|
|
|
27
28
|
sends = "scripts:ex_sends"
|
|
28
29
|
xair = "scripts:test_xair"
|
|
29
30
|
x32 = "scripts:test_x32"
|
|
31
|
+
all = "scripts:test_all"
|
|
32
|
+
|
|
33
|
+
[tool.tox]
|
|
34
|
+
legacy_tox_ini = """
|
|
35
|
+
[tox]
|
|
36
|
+
envlist = py310,py311,py312
|
|
37
|
+
|
|
38
|
+
[testenv]
|
|
39
|
+
allowlist_externals = poetry
|
|
40
|
+
commands =
|
|
41
|
+
poetry install -v
|
|
42
|
+
poetry run pytest tests/
|
|
43
|
+
"""
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class XAirRemoteError(Exception):
|
|
2
|
+
"""Base error class for XAIR Remote."""
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class XAirRemoteConnectionTimeoutError(XAirRemoteError):
|
|
6
|
+
"""Exception raised when a connection attempt times out"""
|
|
7
|
+
|
|
8
|
+
def __init__(self, ip, port):
|
|
9
|
+
self.ip = ip
|
|
10
|
+
self.port = port
|
|
11
|
+
|
|
12
|
+
super().__init__(
|
|
13
|
+
f"Timeout attempting to connect to mixer at {self.ip}:{self.port}"
|
|
14
|
+
)
|
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
import functools
|
|
2
|
+
import time
|
|
2
3
|
from math import exp, log
|
|
3
4
|
|
|
5
|
+
from .errors import XAirRemoteConnectionTimeoutError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def timeout(func):
|
|
9
|
+
"""
|
|
10
|
+
Times out the validate_connection function once time elapsed exceeds remote.connect_timeout.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
@functools.wraps(func)
|
|
14
|
+
def wrapper(*args, **kwargs):
|
|
15
|
+
remote, *_ = args
|
|
16
|
+
|
|
17
|
+
err = None
|
|
18
|
+
start = time.time()
|
|
19
|
+
while time.time() < start + remote.connect_timeout:
|
|
20
|
+
try:
|
|
21
|
+
func(*args, **kwargs)
|
|
22
|
+
remote.logger.debug(f"login time: {round(time.time() - start, 2)}")
|
|
23
|
+
err = None
|
|
24
|
+
break
|
|
25
|
+
except XAirRemoteConnectionTimeoutError as e:
|
|
26
|
+
err = e
|
|
27
|
+
continue
|
|
28
|
+
if err:
|
|
29
|
+
raise err
|
|
30
|
+
|
|
31
|
+
return wrapper
|
|
32
|
+
|
|
4
33
|
|
|
5
34
|
def lin_get(min, max, val):
|
|
6
35
|
return min + (max - min) * val
|
|
@@ -14,11 +14,11 @@ from pythonosc.dispatcher import Dispatcher
|
|
|
14
14
|
from pythonosc.osc_message_builder import OscMessageBuilder
|
|
15
15
|
from pythonosc.osc_server import BlockingOSCUDPServer
|
|
16
16
|
|
|
17
|
-
from . import adapter, kinds
|
|
17
|
+
from . import adapter, kinds, util
|
|
18
18
|
from .bus import Bus
|
|
19
19
|
from .config import Config
|
|
20
20
|
from .dca import DCA
|
|
21
|
-
from .errors import XAirRemoteError
|
|
21
|
+
from .errors import XAirRemoteConnectionTimeoutError, XAirRemoteError
|
|
22
22
|
from .fx import FX, FXSend
|
|
23
23
|
from .kinds import KindMap
|
|
24
24
|
from .lr import LR
|
|
@@ -47,8 +47,6 @@ class OSCClientServer(BlockingOSCUDPServer):
|
|
|
47
47
|
class XAirRemote(abc.ABC):
|
|
48
48
|
"""Handles the communication with the mixer via the OSC protocol"""
|
|
49
49
|
|
|
50
|
-
_CONNECT_TIMEOUT = 0.5
|
|
51
|
-
|
|
52
50
|
_info_response = []
|
|
53
51
|
|
|
54
52
|
def __init__(self, **kwargs):
|
|
@@ -57,6 +55,7 @@ class XAirRemote(abc.ABC):
|
|
|
57
55
|
self.xair_ip = kwargs["ip"] or self._ip_from_toml()
|
|
58
56
|
self.xair_port = kwargs["port"]
|
|
59
57
|
self._delay = kwargs["delay"]
|
|
58
|
+
self.connect_timeout = kwargs["connect_timeout"]
|
|
60
59
|
self.logger = logger.getChild(self.__class__.__name__)
|
|
61
60
|
if not self.xair_ip:
|
|
62
61
|
raise XAirRemoteError("No valid ip detected")
|
|
@@ -74,13 +73,10 @@ class XAirRemote(abc.ABC):
|
|
|
74
73
|
conn = tomllib.load(f)
|
|
75
74
|
return conn["connection"].get("ip")
|
|
76
75
|
|
|
76
|
+
@util.timeout
|
|
77
77
|
def validate_connection(self):
|
|
78
|
-
self.
|
|
79
|
-
|
|
80
|
-
if not self.info_response:
|
|
81
|
-
raise XAirRemoteError(
|
|
82
|
-
"Failed to setup OSC connection to mixer. Please check for correct ip address."
|
|
83
|
-
)
|
|
78
|
+
if not self.query("/xinfo"):
|
|
79
|
+
raise XAirRemoteConnectionTimeoutError(self.xair_ip, self.xair_port)
|
|
84
80
|
self.logger.info(
|
|
85
81
|
f"Successfully connected to {self.info_response[2]} at {self.info_response[0]}."
|
|
86
82
|
)
|
|
@@ -117,7 +113,12 @@ def _make_remote(kind: KindMap) -> XAirRemote:
|
|
|
117
113
|
"""
|
|
118
114
|
|
|
119
115
|
def init_x32(self, *args, **kwargs):
|
|
120
|
-
defaultkwargs = {
|
|
116
|
+
defaultkwargs = {
|
|
117
|
+
"ip": None,
|
|
118
|
+
"port": 10023,
|
|
119
|
+
"delay": 0.02,
|
|
120
|
+
"connect_timeout": 2,
|
|
121
|
+
}
|
|
121
122
|
kwargs = defaultkwargs | kwargs
|
|
122
123
|
XAirRemote.__init__(self, *args, **kwargs)
|
|
123
124
|
self.kind = kind
|
|
@@ -135,7 +136,12 @@ def _make_remote(kind: KindMap) -> XAirRemote:
|
|
|
135
136
|
self.config = Config.make(self)
|
|
136
137
|
|
|
137
138
|
def init_xair(self, *args, **kwargs):
|
|
138
|
-
defaultkwargs = {
|
|
139
|
+
defaultkwargs = {
|
|
140
|
+
"ip": None,
|
|
141
|
+
"port": 10024,
|
|
142
|
+
"delay": 0.02,
|
|
143
|
+
"connect_timeout": 2,
|
|
144
|
+
}
|
|
139
145
|
kwargs = defaultkwargs | kwargs
|
|
140
146
|
XAirRemote.__init__(self, *args, **kwargs)
|
|
141
147
|
self.kind = kind
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|