xair-api 2.2.6__py3-none-any.whl → 2.3.2__py3-none-any.whl

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/bus.py CHANGED
@@ -1,8 +1,11 @@
1
1
  import abc
2
+ import logging
2
3
 
3
4
  from .meta import mute_prop
4
5
  from .shared import EQ, GEQ, Config, Dyn, Group, Insert, Mix
5
6
 
7
+ logger = logging.getLogger(__name__)
8
+
6
9
 
7
10
  class IBus(abc.ABC):
8
11
  """Abstract Base Class for buses"""
@@ -10,6 +13,7 @@ class IBus(abc.ABC):
10
13
  def __init__(self, remote, index: int):
11
14
  self._remote = remote
12
15
  self.index = index + 1
16
+ self.logger = logger.getChild(self.__class__.__name__)
13
17
 
14
18
  def getter(self, param: str):
15
19
  return self._remote.query(f"{self.address}/{param}")
xair_api/config.py CHANGED
@@ -1,15 +1,18 @@
1
1
  import abc
2
+ import logging
2
3
 
3
4
  from . import kinds, util
4
- from .errors import XAirRemoteError
5
5
  from .meta import bool_prop
6
6
 
7
+ logger = logging.getLogger(__name__)
8
+
7
9
 
8
10
  class IConfig(abc.ABC):
9
11
  """Abstract Base Class for config"""
10
12
 
11
13
  def __init__(self, remote):
12
14
  self._remote = remote
15
+ self.logger = logger.getChild(self.__class__.__name__)
13
16
 
14
17
  def getter(self, param: str):
15
18
  return self._remote.query(f"{self.address}/{param}")
@@ -114,7 +117,9 @@ class Config(IConfig):
114
117
  @sourcetrim.setter
115
118
  def sourcetrim(self, val: float):
116
119
  if not -18 <= val <= 18:
117
- raise XAirRemoteError("expected value in range -18.0 to 18.0")
120
+ self.logger.warning(
121
+ f"sourcetrim got {val}, expected value in range -18.0 to 18.0"
122
+ )
118
123
  self.setter("sourcetrim", util.lin_set(-18, 18, val))
119
124
 
120
125
  @property
@@ -140,7 +145,9 @@ class Config(IConfig):
140
145
  @dimgain.setter
141
146
  def dimgain(self, val: int):
142
147
  if not -40 <= val <= 0:
143
- raise XAirRemoteError("expected value in range -40 to 0")
148
+ self.logger.warning(
149
+ f"dimgain got {val}, expected value in range -40 to 0"
150
+ )
144
151
  self.setter("dimatt", util.lin_set(-40, 0, val))
145
152
 
146
153
  @property
xair_api/dca.py CHANGED
@@ -1,4 +1,7 @@
1
1
  import abc
2
+ import logging
3
+
4
+ logger = logging.getLogger(__name__)
2
5
 
3
6
 
4
7
  class IDCA(abc.ABC):
@@ -7,6 +10,7 @@ class IDCA(abc.ABC):
7
10
  def __init__(self, remote, index: int):
8
11
  self._remote = remote
9
12
  self.index = index + 1
13
+ self.logger = logger.getChild(self.__class__.__name__)
10
14
 
11
15
  def getter(self, param: str) -> tuple:
12
16
  return self._remote.query(f"{self.address}/{param}")
xair_api/errors.py CHANGED
@@ -1,2 +1,14 @@
1
1
  class XAirRemoteError(Exception):
2
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
+ )
xair_api/fx.py CHANGED
@@ -1,8 +1,11 @@
1
1
  import abc
2
+ import logging
2
3
 
3
4
  from .meta import mute_prop
4
5
  from .shared import Config, Group, Mix
5
6
 
7
+ logger = logging.getLogger(__name__)
8
+
6
9
 
7
10
  class IFX(abc.ABC):
8
11
  """Abstract Base Class for fxs"""
@@ -10,6 +13,7 @@ class IFX(abc.ABC):
10
13
  def __init__(self, remote, index: int):
11
14
  self._remote = remote
12
15
  self.index = index + 1
16
+ self.logger = logger.getChild(self.__class__.__name__)
13
17
 
14
18
  def getter(self, param: str):
15
19
  return self._remote.query(f"{self.address}/{param}")
xair_api/lr.py CHANGED
@@ -1,9 +1,12 @@
1
1
  import abc
2
+ import logging
2
3
  from typing import Optional
3
4
 
4
5
  from .meta import mute_prop
5
6
  from .shared import EQ, GEQ, Config, Dyn, Insert, Mix
6
7
 
8
+ logger = logging.getLogger(__name__)
9
+
7
10
 
8
11
  class ILR(abc.ABC):
9
12
  """Abstract Base Class for lr"""
@@ -12,6 +15,7 @@ class ILR(abc.ABC):
12
15
  self._remote = remote
13
16
  if index is not None:
14
17
  self.index = index + 1
18
+ self.logger = logger.getChild(self.__class__.__name__)
15
19
 
16
20
  def getter(self, param: str):
17
21
  return self._remote.query(f"{self.address}/{param}")
xair_api/meta.py CHANGED
@@ -1,4 +1,3 @@
1
- from .errors import XAirRemoteError
2
1
  from .util import lin_get, lin_set
3
2
 
4
3
 
@@ -58,7 +57,9 @@ def geq_prop(param):
58
57
 
59
58
  def fset(self, val):
60
59
  if not -15 <= val <= 15:
61
- raise XAirRemoteError("expected value in range -15.0 to 15.0")
60
+ self.logger.warning(
61
+ f"slider_{param} got {val}, expected value in range -15.0 to 15.0"
62
+ )
62
63
  self.setter(param, lin_set(-15, 15, val))
63
64
 
64
65
  return property(fget, fset)
xair_api/rtn.py CHANGED
@@ -1,9 +1,12 @@
1
1
  import abc
2
+ import logging
2
3
  from typing import Optional
3
4
 
4
5
  from .meta import mute_prop
5
6
  from .shared import EQ, Config, Group, Mix, Preamp, Send
6
7
 
8
+ logger = logging.getLogger(__name__)
9
+
7
10
 
8
11
  class IRtn(abc.ABC):
9
12
  """Abstract Base Class for rtn"""
@@ -12,6 +15,7 @@ class IRtn(abc.ABC):
12
15
  self._remote = remote
13
16
  if index is not None:
14
17
  self.index = index + 1
18
+ self.logger = logger.getChild(self.__class__.__name__)
15
19
 
16
20
  def getter(self, param: str):
17
21
  return self._remote.query(f"{self.address}/{param}")
xair_api/shared.py CHANGED
@@ -1,7 +1,6 @@
1
1
  from typing import Optional, Union
2
2
 
3
3
  from . import util
4
- from .errors import XAirRemoteError
5
4
  from .meta import geq_prop
6
5
 
7
6
  """
@@ -61,7 +60,9 @@ class Preamp:
61
60
  @usbtrim.setter
62
61
  def usbtrim(self, val: float):
63
62
  if not -18 <= val <= 18:
64
- raise XAirRemoteError("expected value in range -18.0 to 18.0")
63
+ self.logger.warning(
64
+ f"usbtrim got {val}, expected value in range -18.0 to 18.0"
65
+ )
65
66
  self.setter("rtntrim", util.lin_set(-18, 18, val))
66
67
 
67
68
  @property
@@ -95,7 +96,9 @@ class Preamp:
95
96
  @highpassfilter.setter
96
97
  def highpassfilter(self, val: int):
97
98
  if not 20 <= val <= 400:
98
- raise XAirRemoteError("expected value in range 20 to 400")
99
+ self.logger.warning(
100
+ f"highpassfilter got {val}, expected value in range 20 to 400"
101
+ )
99
102
  self.setter("hpf", util.log_set(20, 400, val))
100
103
 
101
104
 
@@ -122,7 +125,7 @@ class Gate:
122
125
  def mode(self, val: str):
123
126
  opts = ("gate", "exp2", "exp3", "exp4", "duck")
124
127
  if val not in opts:
125
- raise XAirRemoteError(f"expected one of {opts}")
128
+ self.logger.warning(f"mode got {val}, expected one of {opts}")
126
129
  self.setter("mode", opts.index(val))
127
130
 
128
131
  @property
@@ -132,7 +135,9 @@ class Gate:
132
135
  @threshold.setter
133
136
  def threshold(self, val: float):
134
137
  if not -80 <= val <= 0:
135
- raise XAirRemoteError("expected value in range -80.0 to 0.0")
138
+ self.logger.warning(
139
+ f"threshold got {val}, expected value in range -80.0 to 0.0"
140
+ )
136
141
  self.setter("thr", util.lin_set(-80, 0, val))
137
142
 
138
143
  @property
@@ -142,7 +147,7 @@ class Gate:
142
147
  @range.setter
143
148
  def range(self, val: int):
144
149
  if not 3 <= val <= 60:
145
- raise XAirRemoteError("expected value in range 3 to 60")
150
+ self.logger.warning(f"range got {val}, expected value in range 3 to 60")
146
151
  self.setter("range", util.lin_set(3, 60, val))
147
152
 
148
153
  @property
@@ -152,7 +157,7 @@ class Gate:
152
157
  @attack.setter
153
158
  def attack(self, val: int):
154
159
  if not 0 <= val <= 120:
155
- raise XAirRemoteError("expected value in range 0 to 120")
160
+ self.logger.warning(f"attack got {val}, expected value in range 0 to 120")
156
161
  self.setter("attack", util.lin_set(0, 120, val))
157
162
 
158
163
  @property
@@ -163,7 +168,9 @@ class Gate:
163
168
  @hold.setter
164
169
  def hold(self, val: float):
165
170
  if not 0.02 <= val <= 2000:
166
- raise XAirRemoteError("expected value in range 0.02 to 2000.0")
171
+ self.logger.warning(
172
+ f"hold got {val}, expected value in range 0.02 to 2000.0"
173
+ )
167
174
  self.setter("hold", util.log_set(0.02, 2000, val))
168
175
 
169
176
  @property
@@ -173,7 +180,7 @@ class Gate:
173
180
  @release.setter
174
181
  def release(self, val: int):
175
182
  if not 5 <= val <= 4000:
176
- raise XAirRemoteError("expected value in range 5 to 4000")
183
+ self.logger.warning(f"release got {val}, expected value in range 5 to 4000")
177
184
  self.setter("release", util.log_set(5, 4000, val))
178
185
 
179
186
  @property
@@ -208,7 +215,9 @@ class Gate:
208
215
  @filterfreq.setter
209
216
  def filterfreq(self, val: Union[float, int]):
210
217
  if not 20 <= val <= 20000:
211
- raise XAirRemoteError("expected value in range 20 to 20000")
218
+ self.logger.warning(
219
+ f"filterfreq got {val}, expected value in range 20 to 20000"
220
+ )
212
221
  self.setter("filter/f", util.log_set(20, 20000, val))
213
222
 
214
223
 
@@ -235,7 +244,7 @@ class Dyn:
235
244
  def mode(self, val: str):
236
245
  opts = ("comp", "exp")
237
246
  if val not in opts:
238
- raise XAirRemoteError(f"expected one of {opts}")
247
+ self.logger.warning(f"mode got {val}, expected one of {opts}")
239
248
  self.setter("mode", opts.index(val))
240
249
 
241
250
  @property
@@ -247,7 +256,7 @@ class Dyn:
247
256
  def det(self, val: str):
248
257
  opts = ("peak", "rms")
249
258
  if val not in opts:
250
- raise XAirRemoteError(f"expected one of {opts}")
259
+ self.logger.warning(f"det got {val}, expected one of {opts}")
251
260
  self.setter("det", opts.index(val))
252
261
 
253
262
  @property
@@ -259,7 +268,7 @@ class Dyn:
259
268
  def env(self, val: str):
260
269
  opts = ("lin", "log")
261
270
  if val not in opts:
262
- raise XAirRemoteError(f"expected one of {opts}")
271
+ self.logger.warning(f"env got {val}, expected one of {opts}")
263
272
  self.setter("env", opts.index(val))
264
273
 
265
274
  @property
@@ -269,7 +278,9 @@ class Dyn:
269
278
  @threshold.setter
270
279
  def threshold(self, val: float):
271
280
  if not -60 <= val <= 0:
272
- raise XAirRemoteError("expected value in range -60.0 to 0")
281
+ self.logger.warning(
282
+ f"threshold got {val}, expected value in range -60.0 to 0"
283
+ )
273
284
  self.setter("thr", util.lin_set(-60, 0, val))
274
285
 
275
286
  @property
@@ -288,7 +299,7 @@ class Dyn:
288
299
  @knee.setter
289
300
  def knee(self, val: int):
290
301
  if not 0 <= val <= 5:
291
- raise XAirRemoteError("expected value in range 0 to 5")
302
+ self.logger.warning(f"knee got {val}, expected value in range 0 to 5")
292
303
  self.setter("knee", util.lin_set(0, 5, val))
293
304
 
294
305
  @property
@@ -298,7 +309,7 @@ class Dyn:
298
309
  @mgain.setter
299
310
  def mgain(self, val: float):
300
311
  if not 0 <= val <= 24:
301
- raise XAirRemoteError("expected value in range 0.0 to 24.0")
312
+ self.logger.warning(f"mgain got {val}, expected value in range 0.0 to 24.0")
302
313
  self.setter("mgain", util.lin_set(0, 24, val))
303
314
 
304
315
  @property
@@ -308,7 +319,7 @@ class Dyn:
308
319
  @attack.setter
309
320
  def attack(self, val: int):
310
321
  if not 0 <= val <= 120:
311
- raise XAirRemoteError("expected value in range 0 to 120")
322
+ self.logger.warning(f"attack got {val}, expected value in range 0 to 120")
312
323
  self.setter("attack", util.lin_set(0, 120, val))
313
324
 
314
325
  @property
@@ -319,7 +330,9 @@ class Dyn:
319
330
  @hold.setter
320
331
  def hold(self, val: float):
321
332
  if not 0.02 <= val <= 2000:
322
- raise XAirRemoteError("expected value in range 0.02 to 2000.0")
333
+ self.logger.warning(
334
+ f"hold got {val}, expected value in range 0.02 to 2000.0"
335
+ )
323
336
  self.setter("hold", util.log_set(0.02, 2000, val))
324
337
 
325
338
  @property
@@ -329,7 +342,7 @@ class Dyn:
329
342
  @release.setter
330
343
  def release(self, val: int):
331
344
  if not 5 <= val <= 4000:
332
- raise XAirRemoteError("expected value in range 5 to 4000")
345
+ self.logger.warning(f"release got {val}, expected value in range 5 to 4000")
333
346
  self.setter("release", util.log_set(5, 4000, val))
334
347
 
335
348
  @property
@@ -339,7 +352,7 @@ class Dyn:
339
352
  @mix.setter
340
353
  def mix(self, val: int):
341
354
  if not 0 <= val <= 100:
342
- raise XAirRemoteError("expected value in range 0 to 100")
355
+ self.logger.warning(f"mix got {val}, expected value in range 0 to 100")
343
356
  self.setter("mix", util.lin_set(0, 100, val))
344
357
 
345
358
  @property
@@ -382,7 +395,9 @@ class Dyn:
382
395
  @filterfreq.setter
383
396
  def filterfreq(self, val: Union[float, int]):
384
397
  if not 20 <= val <= 20000:
385
- raise XAirRemoteError("expected value in range 20 to 20000")
398
+ self.logger.warning(
399
+ f"filterfreq got {val}, expected value in range 20 to 20000"
400
+ )
386
401
  self.setter("filter/f", util.log_set(20, 20000, val))
387
402
 
388
403
 
@@ -462,7 +477,7 @@ class EQ:
462
477
  def mode(self, val: str):
463
478
  opts = ("peq", "geq", "teq")
464
479
  if val not in opts:
465
- raise XAirRemoteError(f"expected one of {opts}")
480
+ self.logger.warning(f"mode got {val}, expected one of {opts}")
466
481
  self.setter("mode", opts.index(val))
467
482
 
468
483
  class EQBand:
@@ -491,7 +506,9 @@ class EQ:
491
506
  @frequency.setter
492
507
  def frequency(self, val: float):
493
508
  if not 20 <= val <= 20000:
494
- raise XAirRemoteError("expected value in range 20.0 to 20000.0")
509
+ self.logger.warning(
510
+ f"frequency got {val}, expected value in range 20.0 to 20000.0"
511
+ )
495
512
  self.setter("f", util.log_set(20, 20000, val))
496
513
 
497
514
  @property
@@ -501,7 +518,9 @@ class EQ:
501
518
  @gain.setter
502
519
  def gain(self, val: float):
503
520
  if not -15 <= val <= 15:
504
- raise XAirRemoteError("expected value in range -15.0 to 15.0")
521
+ self.logger.warning(
522
+ f"gain got {val}, expected value in range -15.0 to 15.0"
523
+ )
505
524
  self.setter("g", util.lin_set(-15, 15, val))
506
525
 
507
526
  @property
@@ -512,7 +531,9 @@ class EQ:
512
531
  @quality.setter
513
532
  def quality(self, val: float):
514
533
  if not 0.3 <= val <= 10:
515
- raise XAirRemoteError("expected value in range 0.3 to 10.0")
534
+ self.logger.warning(
535
+ f"quality got {val}, expected value in range 0.3 to 10.0"
536
+ )
516
537
  self.setter("q", util.log_set(0.3, 10, val))
517
538
 
518
539
 
@@ -620,7 +641,9 @@ class Automix:
620
641
  @weight.setter
621
642
  def weight(self, val: float):
622
643
  if not -12 <= val <= 12:
623
- raise XAirRemoteError("expected value in range -12.0 to 12.0")
644
+ self.logger.warning(
645
+ f"weight got {val}, expected value in range -12.0 to 12.0"
646
+ )
624
647
  self.setter("weight", util.lin_set(-12, 12, val))
625
648
 
626
649
 
xair_api/strip.py CHANGED
@@ -1,8 +1,11 @@
1
1
  import abc
2
+ import logging
2
3
 
3
4
  from .meta import mute_prop
4
5
  from .shared import EQ, Automix, Config, Dyn, Gate, Group, Insert, Mix, Preamp, Send
5
6
 
7
+ logger = logging.getLogger(__name__)
8
+
6
9
 
7
10
  class IStrip(abc.ABC):
8
11
  """Abstract Base Class for strips"""
@@ -10,6 +13,7 @@ class IStrip(abc.ABC):
10
13
  def __init__(self, remote, index: int):
11
14
  self._remote = remote
12
15
  self.index = index + 1
16
+ self.logger = logger.getChild(self.__class__.__name__)
13
17
 
14
18
  def getter(self, param: str) -> tuple:
15
19
  return self._remote.query(f"{self.address}/{param}")
xair_api/util.py CHANGED
@@ -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
xair_api/xair.py CHANGED
@@ -14,17 +14,19 @@ 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
25
25
  from .rtn import AuxRtn, FxRtn
26
26
  from .strip import Strip
27
27
 
28
+ logger = logging.getLogger(__name__)
29
+
28
30
 
29
31
  class OSCClientServer(BlockingOSCUDPServer):
30
32
  def __init__(self, address: str, dispatcher: Dispatcher):
@@ -45,10 +47,6 @@ class OSCClientServer(BlockingOSCUDPServer):
45
47
  class XAirRemote(abc.ABC):
46
48
  """Handles the communication with the mixer via the OSC protocol"""
47
49
 
48
- logger = logging.getLogger("xair.xairremote")
49
-
50
- _CONNECT_TIMEOUT = 0.5
51
-
52
50
  _info_response = []
53
51
 
54
52
  def __init__(self, **kwargs):
@@ -57,6 +55,8 @@ 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"]
59
+ self.logger = logger.getChild(self.__class__.__name__)
60
60
  if not self.xair_ip:
61
61
  raise XAirRemoteError("No valid ip detected")
62
62
  self.server = OSCClientServer((self.xair_ip, self.xair_port), dispatcher)
@@ -73,13 +73,10 @@ class XAirRemote(abc.ABC):
73
73
  conn = tomllib.load(f)
74
74
  return conn["connection"].get("ip")
75
75
 
76
+ @util.timeout
76
77
  def validate_connection(self):
77
- self.send("/xinfo")
78
- time.sleep(self._CONNECT_TIMEOUT)
79
- if not self.info_response:
80
- raise XAirRemoteError(
81
- "Failed to setup OSC connection to mixer. Please check for correct ip address."
82
- )
78
+ if not self.query("/xinfo"):
79
+ raise XAirRemoteConnectionTimeoutError(self.xair_ip, self.xair_port)
83
80
  self.logger.info(
84
81
  f"Successfully connected to {self.info_response[2]} at {self.info_response[0]}."
85
82
  )
@@ -116,7 +113,12 @@ def _make_remote(kind: KindMap) -> XAirRemote:
116
113
  """
117
114
 
118
115
  def init_x32(self, *args, **kwargs):
119
- defaultkwargs = {"ip": None, "port": 10023, "delay": 0.02}
116
+ defaultkwargs = {
117
+ "ip": None,
118
+ "port": 10023,
119
+ "delay": 0.02,
120
+ "connect_timeout": 2,
121
+ }
120
122
  kwargs = defaultkwargs | kwargs
121
123
  XAirRemote.__init__(self, *args, **kwargs)
122
124
  self.kind = kind
@@ -134,7 +136,12 @@ def _make_remote(kind: KindMap) -> XAirRemote:
134
136
  self.config = Config.make(self)
135
137
 
136
138
  def init_xair(self, *args, **kwargs):
137
- defaultkwargs = {"ip": None, "port": 10024, "delay": 0.02}
139
+ defaultkwargs = {
140
+ "ip": None,
141
+ "port": 10024,
142
+ "delay": 0.02,
143
+ "connect_timeout": 2,
144
+ }
138
145
  kwargs = defaultkwargs | kwargs
139
146
  XAirRemote.__init__(self, *args, **kwargs)
140
147
  self.kind = kind
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xair-api
3
- Version: 2.2.6
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=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
 
@@ -139,7 +140,7 @@ Contains the subclasses:
139
140
  ### `Strip`
140
141
 
141
142
  Contains the subclasses:
142
- (`Config`, `Preamp`, `Gate`, `Dyn`, `Insert`, `GEQ`, `EQ`, `Mix`, `Group`, `Automix`)
143
+ (`Config`, `Preamp`, `Gate`, `Dyn`, `Insert`, `GEQ`, `EQ`, `Mix`, `Group`, `Automix`, `Send`)
143
144
 
144
145
  ### `Bus`
145
146
 
@@ -154,12 +155,12 @@ Contains the subclasses:
154
155
  ### `FXRtn`
155
156
 
156
157
  Contains the subclasses:
157
- (`Config`, `Preamp`, `EQ`, `Mix`, `Group`)
158
+ (`Config`, `Preamp`, `EQ`, `Mix`, `Group`, `Send`)
158
159
 
159
160
  ### `AuxRtn`
160
161
 
161
162
  Contains the subclasses:
162
- (`Config`, `Preamp`, `EQ`, `Mix`, `Group`)
163
+ (`Config`, `Preamp`, `EQ`, `Mix`, `Group`, `Send`)
163
164
 
164
165
  ### `Subclasses`
165
166
 
@@ -306,6 +307,12 @@ tuple containing a class for each mute group
306
307
 
307
308
  for example: `config.mute_group[0].on = True`
308
309
 
310
+ ### `Send`
311
+
312
+ - `level`: float, -inf to 10.0
313
+
314
+ for example: `mixer.strip[10].send[3].level = -16.5`
315
+
309
316
  ### XAirRemote class (lower level)
310
317
 
311
318
  Send an OSC command directly to the mixer
@@ -329,6 +336,14 @@ for example:
329
336
  print(mixer.query("/ch/01/mix/on"))
330
337
  ```
331
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
+
332
347
  ### `Tests`
333
348
 
334
349
  Unplug any expensive equipment before running tests.
@@ -0,0 +1,20 @@
1
+ xair_api/__init__.py,sha256=na_Zd_yo8E1LCoeWrAPJR68Ygdm5R8RRrlqb-UnWMtA,73
2
+ xair_api/adapter.py,sha256=icQXeqrYu6iWOJbke6zXdOzxyhAV__dXKrCnuDbZAUU,797
3
+ xair_api/bus.py,sha256=digswx5ApbLCpF6R7_8OqfvnJ8C9JIFpe8MFxKXbSB0,1771
4
+ xair_api/config.py,sha256=ditmhP770trYIu7eouw4pU3BgOtXwOB8dearYJbhSuw,5853
5
+ xair_api/dca.py,sha256=C-wyBqeAi0qr1qrOKefyIWsJwI8ebs2iV83Q2iC67-k,1443
6
+ xair_api/errors.py,sha256=rfFmAW6QitHe0iB56M48He-qsbvDaKe1_AN_j4-9oUA,411
7
+ xair_api/fx.py,sha256=AzjgpJSHDCWwWRGCWxeGwwsm8jcxl3fJykprk9cwSUM,1811
8
+ xair_api/kinds.py,sha256=ulJJhLpiUuOw5Ir7Q3CQbmAKrd33xq8CIHpAFc5zEdw,1119
9
+ xair_api/lr.py,sha256=WL5YnDeLeJPxIK5OdTqZQ3s6UEfQ3-onz99OEdi0-mE,1788
10
+ xair_api/meta.py,sha256=iUWPSP4QcWMW6gyLc5SGDJ49pKZgJrHzFphtL6OFptE,1564
11
+ xair_api/rtn.py,sha256=lOTGSkxsYpc4usIba-reZSRmfa-7JIr_FTThSw6BdLY,3177
12
+ xair_api/shared.py,sha256=ABVTgx9sIH9zZLJLKeZBrhdMXj-WGNuggxrqjn8oa3M,19171
13
+ xair_api/strip.py,sha256=pAFX0Ssq1kC9BghGJhd6ShJ0on16DbkWoickH0jA-Jg,2082
14
+ xair_api/util.py,sha256=Rd2eGhqIjFe29s-0ffQGzs9p5lXsfCRJ91i6BPEVzxE,2263
15
+ xair_api/xair.py,sha256=60ZAZVj0dWmVfcedFtB_rEbv6fnyb-7nP-Z1ltAeqUs,6384
16
+ xair_api-2.3.2.dist-info/entry_points.txt,sha256=hlKDU0C0XSGDitHXAvt6YQfmI99p3eJBaoQqEQhpH2U,126
17
+ xair_api-2.3.2.dist-info/LICENSE,sha256=m2fbtv9II-iQqimTd4zjgynL5vuEqGXauLSDJZycYIo,1124
18
+ xair_api-2.3.2.dist-info/METADATA,sha256=OhG5fjrYkW_wVbEFE6yIbaup5Owe0rz2e1scbLIX2rg,8868
19
+ xair_api-2.3.2.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
20
+ xair_api-2.3.2.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  [console_scripts]
2
+ all=scripts:test_all
2
3
  obs=scripts:ex_obs
3
4
  sends=scripts:ex_sends
4
5
  x32=scripts:test_x32
@@ -1,20 +0,0 @@
1
- xair_api/__init__.py,sha256=na_Zd_yo8E1LCoeWrAPJR68Ygdm5R8RRrlqb-UnWMtA,73
2
- xair_api/adapter.py,sha256=icQXeqrYu6iWOJbke6zXdOzxyhAV__dXKrCnuDbZAUU,797
3
- xair_api/bus.py,sha256=l8lVl5lT7h-Q0X_nsHeXe2E4wssoRuxaH0Re45DaAuc,1651
4
- xair_api/config.py,sha256=GQjYVm_RskdkYiUcUsTmCv3I9sOw62unD9sRESnSh0E,5651
5
- xair_api/dca.py,sha256=IjAMQ_t5XPvS9unk8GxjurnnGLA9GYxMNU6ZQYiMeKA,1323
6
- xair_api/errors.py,sha256=RAqGQ3gndR9l8c_RfEBKC0tMsa5_n8F7o3X7ppVHfL8,80
7
- xair_api/fx.py,sha256=OLoWFTbRPRt8PdFtFsGVAnEbre_Wb805Nql5A0sPyig,1691
8
- xair_api/kinds.py,sha256=ulJJhLpiUuOw5Ir7Q3CQbmAKrd33xq8CIHpAFc5zEdw,1119
9
- xair_api/lr.py,sha256=qQNBnsMUgAs-xh_-brxsNc9N4DiPs0JCTL-yIVjNsy8,1668
10
- xair_api/meta.py,sha256=NngNXwNCoZbgLJpdP3W5oqx2LylRnbXupeaHslFmZkY,1544
11
- xair_api/rtn.py,sha256=sPow_gCGynEL1lZPLWK-Xh6SxnfnkfUDWEkha8IVlFM,3057
12
- xair_api/shared.py,sha256=k7tn6jTD7c7ghDQ1GpkRBYksCf50lRUiX1l-8JYXHnw,18376
13
- xair_api/strip.py,sha256=ynrMYx2Ne9cqtU8MiPQoRHh0ZmQDtLFb5yksW-1-gg4,1962
14
- xair_api/util.py,sha256=VYgSWxKXnvD3tu564wbr5PTdODNrmGNnsZErER5hY3I,1485
15
- xair_api/xair.py,sha256=LLynLdXSZ1uanmoONFBhDHiy7DwvwIpFAZrgUe-K2IU,6210
16
- xair_api-2.2.6.dist-info/entry_points.txt,sha256=p2vlpkx3x9BZ3Mslqg2ngV3g-mdqwB14oEltOqi8kgg,105
17
- xair_api-2.2.6.dist-info/LICENSE,sha256=m2fbtv9II-iQqimTd4zjgynL5vuEqGXauLSDJZycYIo,1124
18
- xair_api-2.2.6.dist-info/METADATA,sha256=dRcLj61IRHWuJywEM8Ihs3ZQaVQs_RD0Eb9gdWXSHaE,8361
19
- xair_api-2.2.6.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
20
- xair_api-2.2.6.dist-info/RECORD,,