mirror of
https://github.com/onyx-and-iris/xair-api-python.git
synced 2025-04-20 12:13:53 +01:00
Compare commits
13 Commits
df2d158618
...
6e017b4afc
Author | SHA1 | Date | |
---|---|---|---|
6e017b4afc | |||
85664c8465 | |||
a3473d5922 | |||
e9ef113b5c | |||
56ec9a17c0 | |||
9a7d98d58b | |||
f3cf215a76 | |||
a62a46d61a | |||
5eeaff2371 | |||
c2cf2fe523 | |||
265c26eb67 | |||
467b769ea4 | |||
27d0811091 |
@ -9,7 +9,14 @@ Before any major/minor/patch bump all unit tests will be run to verify they pass
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- [ ]
|
||||
- [x] Send class mixed into Strip, AuxRtn, FxRtn. May now be accessed with {Class}.send
|
||||
- [x] Sends example added
|
||||
|
||||
## [2.2.0] - 2022-11-08
|
||||
|
||||
### Added
|
||||
|
||||
- mute prop to Bus, FX, LR, RTN, Strip classes.
|
||||
|
||||
## [2.1.0] - 2022-11-08
|
||||
|
||||
|
@ -70,7 +70,7 @@ The following keyword arguments may be passed:
|
||||
|
||||
- `ip`: ip address of the mixer
|
||||
- `port`: mixer port, defaults to 10023 for x32 and 10024 for xair
|
||||
- `delay`: a delay between each command, defaults to 20ms.
|
||||
- `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.
|
||||
|
||||
## API
|
||||
|
24
examples/sends/__main__.py
Normal file
24
examples/sends/__main__.py
Normal file
@ -0,0 +1,24 @@
|
||||
import logging
|
||||
|
||||
import xair_api
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
|
||||
def main():
|
||||
with xair_api.connect("XR18", ip="mixer.local") as mixer:
|
||||
for send in mixer.strip[0].send:
|
||||
send.level = -22.8
|
||||
|
||||
mixer.strip[15].send[0].level = -16.5
|
||||
print(mixer.strip[15].send[0].level)
|
||||
|
||||
mixer.auxreturn.send[0].level = -15.5
|
||||
print(mixer.auxreturn.send[0].level)
|
||||
|
||||
mixer.fxreturn[0].send[0].level = -14.5
|
||||
print(mixer.fxreturn[0].send[0].level)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,12 +1,19 @@
|
||||
import obsws_python as obs
|
||||
|
||||
import xair_api
|
||||
|
||||
|
||||
class Observer:
|
||||
def __init__(self, mixer):
|
||||
self._mixer = mixer
|
||||
self._cl = obs.EventClient()
|
||||
self._cl.callback.register(self.on_current_program_scene_changed)
|
||||
self._client = obs.EventClient()
|
||||
self._client.callback.register(self.on_current_program_scene_changed)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||
self._client.disconnect()
|
||||
|
||||
def on_current_program_scene_changed(self, data):
|
||||
scene = data.scene_name
|
||||
@ -28,11 +35,9 @@ class Observer:
|
||||
|
||||
def main():
|
||||
with xair_api.connect("MR18", ip="mixer.local") as mixer:
|
||||
Observer(mixer)
|
||||
|
||||
while cmd := input("<Enter> to exit\n"):
|
||||
if not cmd:
|
||||
break
|
||||
with Observer(mixer):
|
||||
while _ := input("Press <Enter> to exit\n"):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "xair-api"
|
||||
version = "2.2.3"
|
||||
version = "2.2.4a0"
|
||||
description = "Remote control Behringer X-Air | Midas MR mixers through OSC"
|
||||
authors = ["onyx-and-iris <code@onyxandiris.online>"]
|
||||
license = "MIT"
|
||||
@ -24,5 +24,6 @@ build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
obs = "scripts:ex_obs"
|
||||
sends = "scripts:ex_sends"
|
||||
xair = "scripts:test_xair"
|
||||
x32 = "scripts:test_x32"
|
||||
|
@ -1,10 +1,16 @@
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def ex_obs():
|
||||
path = Path.cwd() / "examples" / "xair_obs" / "."
|
||||
subprocess.run(["py", str(path)])
|
||||
subprocess.run([sys.executable, str(path)])
|
||||
|
||||
|
||||
def ex_sends():
|
||||
path = Path.cwd() / "examples" / "sends" / "."
|
||||
subprocess.run([sys.executable, str(path)])
|
||||
|
||||
|
||||
def test_xair():
|
||||
|
@ -1,9 +1,8 @@
|
||||
import abc
|
||||
|
||||
from . import kinds
|
||||
from . import kinds, util
|
||||
from .errors import XAirRemoteError
|
||||
from .meta import bool_prop
|
||||
from .util import _get_level_val, _set_level_val, lin_get, lin_set
|
||||
|
||||
|
||||
class IConfig(abc.ABC):
|
||||
@ -91,13 +90,14 @@ class Config(IConfig):
|
||||
return f"{root}/solo"
|
||||
|
||||
@property
|
||||
@util.db_from
|
||||
def level(self) -> float:
|
||||
retval = self.getter("level")[0]
|
||||
return _get_level_val(retval)
|
||||
return self.getter("level")[0]
|
||||
|
||||
@level.setter
|
||||
@util.db_to
|
||||
def level(self, val: float):
|
||||
_set_level_val(self, val)
|
||||
self.setter("level", val)
|
||||
|
||||
@property
|
||||
def source(self) -> int:
|
||||
@ -109,13 +109,13 @@ class Config(IConfig):
|
||||
|
||||
@property
|
||||
def sourcetrim(self) -> float:
|
||||
return round(lin_get(-18, 18, self.getter("sourcetrim")[0]), 1)
|
||||
return round(util.lin_get(-18, 18, self.getter("sourcetrim")[0]), 1)
|
||||
|
||||
@sourcetrim.setter
|
||||
def sourcetrim(self, val: float):
|
||||
if not -18 <= val <= 18:
|
||||
raise XAirRemoteError("expected value in range -18.0 to 18.0")
|
||||
self.setter("sourcetrim", lin_set(-18, 18, val))
|
||||
self.setter("sourcetrim", util.lin_set(-18, 18, val))
|
||||
|
||||
@property
|
||||
def chmode(self) -> bool:
|
||||
@ -135,13 +135,13 @@ class Config(IConfig):
|
||||
|
||||
@property
|
||||
def dimgain(self) -> int:
|
||||
return int(lin_get(-40, 0, self.getter("dimatt")[0]))
|
||||
return int(util.lin_get(-40, 0, self.getter("dimatt")[0]))
|
||||
|
||||
@dimgain.setter
|
||||
def dimgain(self, val: int):
|
||||
if not -40 <= val <= 0:
|
||||
raise XAirRemoteError("expected value in range -40 to 0")
|
||||
self.setter("dimatt", lin_set(-40, 0, val))
|
||||
self.setter("dimatt", util.lin_set(-40, 0, val))
|
||||
|
||||
@property
|
||||
def dim(self) -> bool:
|
||||
|
@ -1,4 +1,2 @@
|
||||
class XAirRemoteError(Exception):
|
||||
"""Base error class for XAIR Remote."""
|
||||
|
||||
pass
|
||||
|
@ -7,7 +7,7 @@ from .shared import EQ, GEQ, Automix, Config, Dyn, Gate, Group, Insert, Mix, Pre
|
||||
|
||||
|
||||
class ILR(abc.ABC):
|
||||
"""Abstract Base Class for buses"""
|
||||
"""Abstract Base Class for lr"""
|
||||
|
||||
def __init__(self, remote, index: Optional[int] = None):
|
||||
self._remote = remote
|
||||
@ -26,7 +26,7 @@ class ILR(abc.ABC):
|
||||
|
||||
|
||||
class LR(ILR):
|
||||
"""Concrete class for buses"""
|
||||
"""Concrete class for lr"""
|
||||
|
||||
@classmethod
|
||||
def make(cls, remote, index=None):
|
||||
|
@ -3,11 +3,23 @@ from typing import Optional
|
||||
|
||||
from .errors import XAirRemoteError
|
||||
from .meta import mute_prop
|
||||
from .shared import EQ, GEQ, Automix, Config, Dyn, Gate, Group, Insert, Mix, Preamp
|
||||
from .shared import (
|
||||
EQ,
|
||||
GEQ,
|
||||
Automix,
|
||||
Config,
|
||||
Dyn,
|
||||
Gate,
|
||||
Group,
|
||||
Insert,
|
||||
Mix,
|
||||
Preamp,
|
||||
Send,
|
||||
)
|
||||
|
||||
|
||||
class IRtn(abc.ABC):
|
||||
"""Abstract Base Class for aux"""
|
||||
"""Abstract Base Class for rtn"""
|
||||
|
||||
def __init__(self, remote, index: Optional[int] = None):
|
||||
self._remote = remote
|
||||
@ -26,13 +38,15 @@ class IRtn(abc.ABC):
|
||||
|
||||
|
||||
class AuxRtn(IRtn):
|
||||
"""Concrete class for aux"""
|
||||
"""Concrete class for auxrtn"""
|
||||
|
||||
@classmethod
|
||||
def make(cls, remote, index=None):
|
||||
"""
|
||||
Factory function for auxrtn
|
||||
|
||||
Creates a mixin of shared subclasses, sets them as class attributes.
|
||||
|
||||
Returns an AuxRtn class of a kind.
|
||||
"""
|
||||
AUXRTN_cls = type(
|
||||
@ -51,6 +65,10 @@ class AuxRtn(IRtn):
|
||||
Group,
|
||||
)
|
||||
},
|
||||
"send": tuple(
|
||||
Send.make(cls, i, remote)
|
||||
for i in range(remote.kind.num_bus + remote.kind.num_fx)
|
||||
),
|
||||
"mute": mute_prop(),
|
||||
},
|
||||
)
|
||||
@ -62,13 +80,15 @@ class AuxRtn(IRtn):
|
||||
|
||||
|
||||
class FxRtn(IRtn):
|
||||
"""Concrete class for rtn"""
|
||||
"""Concrete class for fxrtn"""
|
||||
|
||||
@classmethod
|
||||
def make(cls, remote, index):
|
||||
"""
|
||||
Factory function for fxrtn
|
||||
|
||||
Creates a mixin of shared subclasses, sets them as class attributes.
|
||||
|
||||
Returns an FxRtn class of a kind.
|
||||
"""
|
||||
FXRTN_cls = type(
|
||||
@ -87,6 +107,10 @@ class FxRtn(IRtn):
|
||||
Group,
|
||||
)
|
||||
},
|
||||
"send": tuple(
|
||||
Send.make(cls, i, remote, index)
|
||||
for i in range(remote.kind.num_bus + remote.kind.num_fx)
|
||||
),
|
||||
"mute": mute_prop(),
|
||||
},
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
from typing import Union
|
||||
from typing import Optional, Union
|
||||
|
||||
from . import util
|
||||
from .errors import XAirRemoteError
|
||||
from .meta import geq_prop
|
||||
from .util import _get_fader_val, _set_fader_val, lin_get, lin_set, log_get, log_set
|
||||
|
||||
"""
|
||||
Classes shared by /ch, /rtn, /rtn/aux, /bus, /fxsend, /lr
|
||||
@ -56,13 +56,13 @@ class Preamp:
|
||||
|
||||
@property
|
||||
def usbtrim(self) -> float:
|
||||
return round(lin_get(-18, 18, self.getter("rtntrim")[0]), 1)
|
||||
return round(util.lin_get(-18, 18, self.getter("rtntrim")[0]), 1)
|
||||
|
||||
@usbtrim.setter
|
||||
def usbtrim(self, val: float):
|
||||
if not -18 <= val <= 18:
|
||||
raise XAirRemoteError("expected value in range -18.0 to 18.0")
|
||||
self.setter("rtntrim", lin_set(-18, 18, val))
|
||||
self.setter("rtntrim", util.lin_set(-18, 18, val))
|
||||
|
||||
@property
|
||||
def usbinput(self) -> bool:
|
||||
@ -90,13 +90,13 @@ class Preamp:
|
||||
|
||||
@property
|
||||
def highpassfilter(self) -> int:
|
||||
return int(log_get(20, 400, self.getter("hpf")[0]))
|
||||
return int(util.log_get(20, 400, self.getter("hpf")[0]))
|
||||
|
||||
@highpassfilter.setter
|
||||
def highpassfilter(self, val: int):
|
||||
if not 20 <= val <= 400:
|
||||
raise XAirRemoteError("expected value in range 20 to 400")
|
||||
self.setter("hpf", log_set(20, 400, val))
|
||||
self.setter("hpf", util.log_set(20, 400, val))
|
||||
|
||||
|
||||
class Gate:
|
||||
@ -127,54 +127,54 @@ class Gate:
|
||||
|
||||
@property
|
||||
def threshold(self) -> float:
|
||||
return round(lin_get(-80, 0, self.getter("thr")[0]), 1)
|
||||
return round(util.lin_get(-80, 0, self.getter("thr")[0]), 1)
|
||||
|
||||
@threshold.setter
|
||||
def threshold(self, val: float):
|
||||
if not -80 <= val <= 0:
|
||||
raise XAirRemoteError("expected value in range -80.0 to 0.0")
|
||||
self.setter("thr", lin_set(-80, 0, val))
|
||||
self.setter("thr", util.lin_set(-80, 0, val))
|
||||
|
||||
@property
|
||||
def range(self) -> int:
|
||||
return int(lin_get(3, 60, self.getter("range")[0]))
|
||||
return int(util.lin_get(3, 60, self.getter("range")[0]))
|
||||
|
||||
@range.setter
|
||||
def range(self, val: int):
|
||||
if not 3 <= val <= 60:
|
||||
raise XAirRemoteError("expected value in range 3 to 60")
|
||||
self.setter("range", lin_set(3, 60, val))
|
||||
self.setter("range", util.lin_set(3, 60, val))
|
||||
|
||||
@property
|
||||
def attack(self) -> int:
|
||||
return int(lin_get(0, 120, self.getter("attack")[0]))
|
||||
return int(util.lin_get(0, 120, self.getter("attack")[0]))
|
||||
|
||||
@attack.setter
|
||||
def attack(self, val: int):
|
||||
if not 0 <= val <= 120:
|
||||
raise XAirRemoteError("expected value in range 0 to 120")
|
||||
self.setter("attack", lin_set(0, 120, val))
|
||||
self.setter("attack", util.lin_set(0, 120, val))
|
||||
|
||||
@property
|
||||
def hold(self) -> Union[float, int]:
|
||||
val = log_get(0.02, 2000, self.getter("hold")[0])
|
||||
val = util.log_get(0.02, 2000, self.getter("hold")[0])
|
||||
return round(val, 1) if val < 100 else int(val)
|
||||
|
||||
@hold.setter
|
||||
def hold(self, val: float):
|
||||
if not 0.02 <= val <= 2000:
|
||||
raise XAirRemoteError("expected value in range 0.02 to 2000.0")
|
||||
self.setter("hold", log_set(0.02, 2000, val))
|
||||
self.setter("hold", util.log_set(0.02, 2000, val))
|
||||
|
||||
@property
|
||||
def release(self) -> int:
|
||||
return int(log_get(5, 4000, self.getter("release")[0]))
|
||||
return int(util.log_get(5, 4000, self.getter("release")[0]))
|
||||
|
||||
@release.setter
|
||||
def release(self, val: int):
|
||||
if not 5 <= val <= 4000:
|
||||
raise XAirRemoteError("expected value in range 5 to 4000")
|
||||
self.setter("release", log_set(5, 4000, val))
|
||||
self.setter("release", util.log_set(5, 4000, val))
|
||||
|
||||
@property
|
||||
def keysource(self):
|
||||
@ -202,14 +202,14 @@ class Gate:
|
||||
|
||||
@property
|
||||
def filterfreq(self) -> Union[float, int]:
|
||||
retval = log_get(20, 20000, self.getter("filter/f")[0])
|
||||
retval = util.log_get(20, 20000, self.getter("filter/f")[0])
|
||||
return int(retval) if retval > 1000 else round(retval, 1)
|
||||
|
||||
@filterfreq.setter
|
||||
def filterfreq(self, val: Union[float, int]):
|
||||
if not 20 <= val <= 20000:
|
||||
raise XAirRemoteError("expected value in range 20 to 20000")
|
||||
self.setter("filter/f", log_set(20, 20000, val))
|
||||
self.setter("filter/f", util.log_set(20, 20000, val))
|
||||
|
||||
|
||||
class Dyn:
|
||||
@ -264,13 +264,13 @@ class Dyn:
|
||||
|
||||
@property
|
||||
def threshold(self) -> float:
|
||||
return round(lin_get(-60, 0, self.getter("thr")[0]), 1)
|
||||
return round(util.lin_get(-60, 0, self.getter("thr")[0]), 1)
|
||||
|
||||
@threshold.setter
|
||||
def threshold(self, val: float):
|
||||
if not -60 <= val <= 0:
|
||||
raise XAirRemoteError("expected value in range -60.0 to 0")
|
||||
self.setter("thr", lin_set(-60, 0, val))
|
||||
self.setter("thr", util.lin_set(-60, 0, val))
|
||||
|
||||
@property
|
||||
def ratio(self) -> Union[float, int]:
|
||||
@ -283,64 +283,64 @@ class Dyn:
|
||||
|
||||
@property
|
||||
def knee(self) -> int:
|
||||
return int(lin_get(0, 5, self.getter("knee")[0]))
|
||||
return int(util.lin_get(0, 5, self.getter("knee")[0]))
|
||||
|
||||
@knee.setter
|
||||
def knee(self, val: int):
|
||||
if not 0 <= val <= 5:
|
||||
raise XAirRemoteError("expected value in range 0 to 5")
|
||||
self.setter("knee", lin_set(0, 5, val))
|
||||
self.setter("knee", util.lin_set(0, 5, val))
|
||||
|
||||
@property
|
||||
def mgain(self) -> float:
|
||||
return round(lin_get(0, 24, self.getter("mgain")[0]), 1)
|
||||
return round(util.lin_get(0, 24, self.getter("mgain")[0]), 1)
|
||||
|
||||
@mgain.setter
|
||||
def mgain(self, val: float):
|
||||
if not 0 <= val <= 24:
|
||||
raise XAirRemoteError("expected value in range 0.0 to 24.0")
|
||||
self.setter("mgain", lin_set(0, 24, val))
|
||||
self.setter("mgain", util.lin_set(0, 24, val))
|
||||
|
||||
@property
|
||||
def attack(self) -> int:
|
||||
return int(lin_get(0, 120, self.getter("attack")[0]))
|
||||
return int(util.lin_get(0, 120, self.getter("attack")[0]))
|
||||
|
||||
@attack.setter
|
||||
def attack(self, val: int):
|
||||
if not 0 <= val <= 120:
|
||||
raise XAirRemoteError("expected value in range 0 to 120")
|
||||
self.setter("attack", lin_set(0, 120, val))
|
||||
self.setter("attack", util.lin_set(0, 120, val))
|
||||
|
||||
@property
|
||||
def hold(self) -> Union[float, int]:
|
||||
val = log_get(0.02, 2000, self.getter("hold")[0])
|
||||
val = util.log_get(0.02, 2000, self.getter("hold")[0])
|
||||
return round(val, 1) if val < 100 else int(val)
|
||||
|
||||
@hold.setter
|
||||
def hold(self, val: float):
|
||||
if not 0.02 <= val <= 2000:
|
||||
raise XAirRemoteError("expected value in range 0.02 to 2000.0")
|
||||
self.setter("hold", log_set(0.02, 2000, val))
|
||||
self.setter("hold", util.log_set(0.02, 2000, val))
|
||||
|
||||
@property
|
||||
def release(self) -> int:
|
||||
return int(log_get(5, 4000, self.getter("release")[0]))
|
||||
return int(util.log_get(5, 4000, self.getter("release")[0]))
|
||||
|
||||
@release.setter
|
||||
def release(self, val: int):
|
||||
if not 5 <= val <= 4000:
|
||||
raise XAirRemoteError("expected value in range 5 to 4000")
|
||||
self.setter("release", log_set(5, 4000, val))
|
||||
self.setter("release", util.log_set(5, 4000, val))
|
||||
|
||||
@property
|
||||
def mix(self) -> int:
|
||||
return int(lin_get(0, 100, self.getter("mix")[0]))
|
||||
return int(util.lin_get(0, 100, self.getter("mix")[0]))
|
||||
|
||||
@mix.setter
|
||||
def mix(self, val: int):
|
||||
if not 0 <= val <= 100:
|
||||
raise XAirRemoteError("expected value in range 0 to 100")
|
||||
self.setter("mix", lin_set(0, 100, val))
|
||||
self.setter("mix", util.lin_set(0, 100, val))
|
||||
|
||||
@property
|
||||
def keysource(self):
|
||||
@ -376,14 +376,14 @@ class Dyn:
|
||||
|
||||
@property
|
||||
def filterfreq(self) -> Union[float, int]:
|
||||
retval = log_get(20, 20000, self.getter("filter/f")[0])
|
||||
retval = util.log_get(20, 20000, self.getter("filter/f")[0])
|
||||
return int(retval) if retval > 1000 else round(retval, 1)
|
||||
|
||||
@filterfreq.setter
|
||||
def filterfreq(self, val: Union[float, int]):
|
||||
if not 20 <= val <= 20000:
|
||||
raise XAirRemoteError("expected value in range 20 to 20000")
|
||||
self.setter("filter/f", log_set(20, 20000, val))
|
||||
self.setter("filter/f", util.log_set(20, 20000, val))
|
||||
|
||||
|
||||
class Insert:
|
||||
@ -467,9 +467,6 @@ class EQ:
|
||||
|
||||
class EQBand:
|
||||
def __init__(self, i, remote, index):
|
||||
if index is None:
|
||||
super(EQ.EQBand, self).__init__(remote)
|
||||
else:
|
||||
super(EQ.EQBand, self).__init__(remote, index)
|
||||
self.i = i
|
||||
|
||||
@ -488,35 +485,35 @@ class EQ:
|
||||
|
||||
@property
|
||||
def frequency(self) -> float:
|
||||
retval = log_get(20, 20000, self.getter("f")[0])
|
||||
retval = util.log_get(20, 20000, self.getter("f")[0])
|
||||
return round(retval, 1)
|
||||
|
||||
@frequency.setter
|
||||
def frequency(self, val: float):
|
||||
if not 20 <= val <= 20000:
|
||||
raise XAirRemoteError("expected value in range 20.0 to 20000.0")
|
||||
self.setter("f", log_set(20, 20000, val))
|
||||
self.setter("f", util.log_set(20, 20000, val))
|
||||
|
||||
@property
|
||||
def gain(self) -> float:
|
||||
return round(lin_get(-15, 15, self.getter("g")[0]), 1)
|
||||
return round(util.lin_get(-15, 15, self.getter("g")[0]), 1)
|
||||
|
||||
@gain.setter
|
||||
def gain(self, val: float):
|
||||
if not -15 <= val <= 15:
|
||||
raise XAirRemoteError("expected value in range -15.0 to 15.0")
|
||||
self.setter("g", lin_set(-15, 15, val))
|
||||
self.setter("g", util.lin_set(-15, 15, val))
|
||||
|
||||
@property
|
||||
def quality(self) -> float:
|
||||
retval = log_get(0.3, 10, self.getter("q")[0])
|
||||
retval = util.log_get(0.3, 10, self.getter("q")[0])
|
||||
return round(retval, 1)
|
||||
|
||||
@quality.setter
|
||||
def quality(self, val: float):
|
||||
if not 0.3 <= val <= 10:
|
||||
raise XAirRemoteError("expected value in range 0.3 to 10.0")
|
||||
self.setter("q", log_set(0.3, 10, val))
|
||||
self.setter("q", util.log_set(0.3, 10, val))
|
||||
|
||||
|
||||
class GEQ:
|
||||
@ -561,13 +558,14 @@ class Mix:
|
||||
self.setter("on", 1 if val else 0)
|
||||
|
||||
@property
|
||||
@util.db_from
|
||||
def fader(self) -> float:
|
||||
retval = self.getter("fader")[0]
|
||||
return _get_fader_val(retval)
|
||||
return self.getter("fader")[0]
|
||||
|
||||
@fader.setter
|
||||
@util.db_to
|
||||
def fader(self, val: float):
|
||||
_set_fader_val(self, val)
|
||||
self.setter("fader", val)
|
||||
|
||||
@property
|
||||
def lr(self) -> bool:
|
||||
@ -617,10 +615,36 @@ class Automix:
|
||||
|
||||
@property
|
||||
def weight(self) -> float:
|
||||
return round(lin_get(-12, 12, self.getter("weight")[0]), 1)
|
||||
return round(util.lin_get(-12, 12, self.getter("weight")[0]), 1)
|
||||
|
||||
@weight.setter
|
||||
def weight(self, val: float):
|
||||
if not -12 <= val <= 12:
|
||||
raise XAirRemoteError("expected value in range -12.0 to 12.0")
|
||||
self.setter("weight", lin_set(-12, 12, val))
|
||||
self.setter("weight", util.lin_set(-12, 12, val))
|
||||
|
||||
|
||||
class Send:
|
||||
def __init__(self, i, remote, index: Optional[int] = None):
|
||||
super(Send, self).__init__(remote, index)
|
||||
self.i = i + 1
|
||||
|
||||
@classmethod
|
||||
def make(cls, _cls, i, remote, index=None):
|
||||
SEND_cls = type("Send", (cls, _cls), {})
|
||||
return SEND_cls(i, remote, index)
|
||||
|
||||
@property
|
||||
def address(self) -> str:
|
||||
root = super(Send, self).address
|
||||
return f"{root}/mix/{str(self.i).zfill(2)}"
|
||||
|
||||
@property
|
||||
@util.db_from
|
||||
def level(self):
|
||||
return self.getter("level")[0]
|
||||
|
||||
@level.setter
|
||||
@util.db_to
|
||||
def level(self, val):
|
||||
self.setter("level", val)
|
||||
|
@ -2,7 +2,19 @@ import abc
|
||||
|
||||
from .errors import XAirRemoteError
|
||||
from .meta import mute_prop
|
||||
from .shared import EQ, GEQ, Automix, Config, Dyn, Gate, Group, Insert, Mix, Preamp
|
||||
from .shared import (
|
||||
EQ,
|
||||
GEQ,
|
||||
Automix,
|
||||
Config,
|
||||
Dyn,
|
||||
Gate,
|
||||
Group,
|
||||
Insert,
|
||||
Mix,
|
||||
Preamp,
|
||||
Send,
|
||||
)
|
||||
|
||||
|
||||
class IStrip(abc.ABC):
|
||||
@ -56,6 +68,10 @@ class Strip(IStrip):
|
||||
Automix,
|
||||
)
|
||||
},
|
||||
"send": tuple(
|
||||
Send.make(cls, i, remote, index)
|
||||
for i in range(remote.kind.num_bus + remote.kind.num_fx)
|
||||
),
|
||||
"mute": mute_prop(),
|
||||
},
|
||||
)
|
||||
|
@ -1,3 +1,4 @@
|
||||
import functools
|
||||
from math import exp, log
|
||||
|
||||
|
||||
@ -17,7 +18,13 @@ def log_set(min, max, val):
|
||||
return log(val / min) / log(max / min)
|
||||
|
||||
|
||||
def _get_fader_val(retval):
|
||||
def db_from(func):
|
||||
"""fader|level converter for getters"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
retval = func(*args, **kwargs)
|
||||
|
||||
if retval >= 1:
|
||||
return 10
|
||||
elif retval >= 0.5:
|
||||
@ -31,47 +38,28 @@ def _get_fader_val(retval):
|
||||
else:
|
||||
return -90
|
||||
|
||||
return wrapper
|
||||
|
||||
def _set_fader_val(self, val):
|
||||
|
||||
def db_to(func):
|
||||
"""fader|level converter for setters"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
param, val = args
|
||||
if val >= 10:
|
||||
self.setter("fader", 1)
|
||||
val = 1
|
||||
elif val >= -10:
|
||||
self.setter("fader", (val + 30) / 40)
|
||||
val = (val + 30) / 40
|
||||
elif val >= -30:
|
||||
self.setter("fader", (val + 50) / 80)
|
||||
val = (val + 50) / 80
|
||||
elif val >= -60:
|
||||
self.setter("fader", (val + 70) / 160)
|
||||
val = (val + 70) / 160
|
||||
elif val >= -90:
|
||||
self.setter("fader", (val + 90) / 480)
|
||||
val = (val + 90) / 480
|
||||
else:
|
||||
self.setter("fader", 0)
|
||||
val = 0
|
||||
|
||||
func(param, val, **kwargs)
|
||||
|
||||
def _get_level_val(retval):
|
||||
if retval >= 1:
|
||||
return 10
|
||||
elif retval >= 0.5:
|
||||
return round((40 * retval) - 30, 1)
|
||||
elif retval >= 0.25:
|
||||
return round((80 * retval) - 50, 1)
|
||||
elif retval >= 0.0625:
|
||||
return round((160 * retval) - 70, 1)
|
||||
elif retval >= 0:
|
||||
return round((480 * retval) - 90, 1)
|
||||
else:
|
||||
return -90
|
||||
|
||||
|
||||
def _set_level_val(self, val):
|
||||
if val >= 10:
|
||||
self.setter("level", 1)
|
||||
elif val >= -10:
|
||||
self.setter("level", (val + 30) / 40)
|
||||
elif val >= -30:
|
||||
self.setter("level", (val + 50) / 80)
|
||||
elif val >= -60:
|
||||
self.setter("level", (val + 70) / 160)
|
||||
elif val >= -90:
|
||||
self.setter("level", (val + 90) / 480)
|
||||
else:
|
||||
self.setter("level", 0)
|
||||
return wrapper
|
||||
|
Loading…
x
Reference in New Issue
Block a user