xair-api 2.4.1__py3-none-any.whl → 2.4.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/__init__.py +3 -3
- xair_api/adapter.py +47 -47
- xair_api/bus.py +66 -66
- xair_api/config.py +207 -207
- xair_api/dca.py +63 -63
- xair_api/errors.py +14 -14
- xair_api/fx.py +74 -74
- xair_api/headamp.py +49 -49
- xair_api/kinds.py +61 -61
- xair_api/lr.py +67 -67
- xair_api/meta.py +75 -75
- xair_api/rtn.py +112 -112
- xair_api/shared.py +674 -673
- xair_api/strip.py +73 -73
- xair_api/util.py +94 -94
- xair_api/xair.py +193 -193
- {xair_api-2.4.1.dist-info → xair_api-2.4.2.dist-info}/METADATA +12 -9
- xair_api-2.4.2.dist-info/RECORD +20 -0
- {xair_api-2.4.1.dist-info → xair_api-2.4.2.dist-info}/WHEEL +1 -1
- {xair_api-2.4.1.dist-info → xair_api-2.4.2.dist-info/licenses}/LICENSE +22 -22
- xair_api-2.4.1.dist-info/RECORD +0 -20
xair_api/xair.py
CHANGED
|
@@ -1,193 +1,193 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import logging
|
|
3
|
-
import threading
|
|
4
|
-
import time
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from typing import Optional, Union
|
|
7
|
-
|
|
8
|
-
try:
|
|
9
|
-
import tomllib
|
|
10
|
-
except ModuleNotFoundError:
|
|
11
|
-
import tomli as tomllib
|
|
12
|
-
|
|
13
|
-
from pythonosc.dispatcher import Dispatcher
|
|
14
|
-
from pythonosc.osc_message_builder import OscMessageBuilder
|
|
15
|
-
from pythonosc.osc_server import BlockingOSCUDPServer
|
|
16
|
-
|
|
17
|
-
from . import adapter, kinds, util
|
|
18
|
-
from .bus import Bus
|
|
19
|
-
from .config import Config
|
|
20
|
-
from .dca import DCA
|
|
21
|
-
from .errors import XAirRemoteConnectionTimeoutError, XAirRemoteError
|
|
22
|
-
from .fx import FX, FXSend
|
|
23
|
-
from .headamp import HeadAmp
|
|
24
|
-
from .kinds import KindMap
|
|
25
|
-
from .lr import LR
|
|
26
|
-
from .rtn import AuxRtn, FxRtn
|
|
27
|
-
from .strip import Strip
|
|
28
|
-
|
|
29
|
-
logger = logging.getLogger(__name__)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class OSCClientServer(BlockingOSCUDPServer):
|
|
33
|
-
def __init__(self, address: str, dispatcher: Dispatcher):
|
|
34
|
-
super().__init__(('', 0), dispatcher)
|
|
35
|
-
self.xr_address = address
|
|
36
|
-
|
|
37
|
-
def send_message(self, address: str, vals: Optional[Union[str, list]]):
|
|
38
|
-
builder = OscMessageBuilder(address=address)
|
|
39
|
-
vals = vals if vals is not None else []
|
|
40
|
-
if not isinstance(vals, list):
|
|
41
|
-
vals = [vals]
|
|
42
|
-
for val in vals:
|
|
43
|
-
builder.add_arg(val)
|
|
44
|
-
msg = builder.build()
|
|
45
|
-
self.socket.sendto(msg.dgram, self.xr_address)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class XAirRemote(abc.ABC):
|
|
49
|
-
"""Handles the communication with the mixer via the OSC protocol"""
|
|
50
|
-
|
|
51
|
-
_info_response = []
|
|
52
|
-
|
|
53
|
-
def __init__(self, **kwargs):
|
|
54
|
-
dispatcher = Dispatcher()
|
|
55
|
-
dispatcher.set_default_handler(self.msg_handler)
|
|
56
|
-
self.xair_ip = kwargs['ip'] or self._ip_from_toml()
|
|
57
|
-
self.xair_port = kwargs['port']
|
|
58
|
-
self._delay = kwargs['delay']
|
|
59
|
-
self.connect_timeout = kwargs['connect_timeout']
|
|
60
|
-
self.logger = logger.getChild(self.__class__.__name__)
|
|
61
|
-
if not self.xair_ip:
|
|
62
|
-
raise XAirRemoteError('No valid ip detected')
|
|
63
|
-
self.server = OSCClientServer((self.xair_ip, self.xair_port), dispatcher)
|
|
64
|
-
|
|
65
|
-
def __enter__(self):
|
|
66
|
-
self.worker = threading.Thread(target=self.run_server, daemon=True)
|
|
67
|
-
self.worker.start()
|
|
68
|
-
self.validate_connection()
|
|
69
|
-
return self
|
|
70
|
-
|
|
71
|
-
def _ip_from_toml(self) -> str:
|
|
72
|
-
filepath = Path.cwd() / 'config.toml'
|
|
73
|
-
with open(filepath, 'rb') as f:
|
|
74
|
-
conn = tomllib.load(f)
|
|
75
|
-
return conn['connection'].get('ip')
|
|
76
|
-
|
|
77
|
-
@util.timeout
|
|
78
|
-
def validate_connection(self):
|
|
79
|
-
if not self.query('/xinfo'):
|
|
80
|
-
raise XAirRemoteConnectionTimeoutError(self.xair_ip, self.xair_port)
|
|
81
|
-
self.logger.info(
|
|
82
|
-
f'Successfully connected to {self.info_response[2]} at {self.info_response[0]}.'
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
@property
|
|
86
|
-
def info_response(self):
|
|
87
|
-
return self._info_response
|
|
88
|
-
|
|
89
|
-
def run_server(self):
|
|
90
|
-
self.server.serve_forever()
|
|
91
|
-
|
|
92
|
-
def msg_handler(self, addr, *data):
|
|
93
|
-
self.logger.debug(f"received: {addr} {data if data else ''}")
|
|
94
|
-
self._info_response = data[:]
|
|
95
|
-
|
|
96
|
-
def send(self, addr: str, param: Optional[str] = None):
|
|
97
|
-
self.logger.debug(f"sending: {addr} {param if param is not None else ''}")
|
|
98
|
-
self.server.send_message(addr, param)
|
|
99
|
-
|
|
100
|
-
def query(self, address):
|
|
101
|
-
self.send(address)
|
|
102
|
-
time.sleep(self._delay)
|
|
103
|
-
return self.info_response
|
|
104
|
-
|
|
105
|
-
def __exit__(self, exc_type, exc_value, exc_tr):
|
|
106
|
-
self.server.shutdown()
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def _make_remote(kind: KindMap) -> XAirRemote:
|
|
110
|
-
"""
|
|
111
|
-
Creates a new XAIR remote class.
|
|
112
|
-
|
|
113
|
-
The returned class will subclass XAirRemote.
|
|
114
|
-
"""
|
|
115
|
-
|
|
116
|
-
def init_x32(self, *args, **kwargs):
|
|
117
|
-
defaultkwargs = {
|
|
118
|
-
'ip': None,
|
|
119
|
-
'port': 10023,
|
|
120
|
-
'delay': 0.02,
|
|
121
|
-
'connect_timeout': 2,
|
|
122
|
-
}
|
|
123
|
-
kwargs = defaultkwargs | kwargs
|
|
124
|
-
XAirRemote.__init__(self, *args, **kwargs)
|
|
125
|
-
self.kind = kind
|
|
126
|
-
self.mainst = adapter.MainStereo.make(self)
|
|
127
|
-
self.mainmono = adapter.MainMono.make(self)
|
|
128
|
-
self.matrix = tuple(
|
|
129
|
-
adapter.Matrix.make(self, i) for i in range(kind.num_matrix)
|
|
130
|
-
)
|
|
131
|
-
self.strip = tuple(Strip.make(self, i) for i in range(kind.num_strip))
|
|
132
|
-
self.bus = tuple(adapter.Bus.make(self, i) for i in range(kind.num_bus))
|
|
133
|
-
self.dca = tuple(DCA(self, i) for i in range(kind.num_dca))
|
|
134
|
-
self.fx = tuple(FX(self, i) for i in range(kind.num_fx))
|
|
135
|
-
self.fxreturn = tuple(adapter.FxRtn.make(self, i) for i in range(kind.num_fx))
|
|
136
|
-
self.auxin = tuple(adapter.AuxRtn.make(self, i) for i in range(kind.num_auxrtn))
|
|
137
|
-
self.config = Config.make(self)
|
|
138
|
-
self.headamp = tuple(adapter.HeadAmp(self, i) for i in range(kind.num_headamp))
|
|
139
|
-
|
|
140
|
-
def init_xair(self, *args, **kwargs):
|
|
141
|
-
defaultkwargs = {
|
|
142
|
-
'ip': None,
|
|
143
|
-
'port': 10024,
|
|
144
|
-
'delay': 0.02,
|
|
145
|
-
'connect_timeout': 2,
|
|
146
|
-
}
|
|
147
|
-
kwargs = defaultkwargs | kwargs
|
|
148
|
-
XAirRemote.__init__(self, *args, **kwargs)
|
|
149
|
-
self.kind = kind
|
|
150
|
-
self.lr = LR.make(self)
|
|
151
|
-
self.strip = tuple(Strip.make(self, i) for i in range(kind.num_strip))
|
|
152
|
-
self.bus = tuple(Bus.make(self, i) for i in range(kind.num_bus))
|
|
153
|
-
self.dca = tuple(DCA(self, i) for i in range(kind.num_dca))
|
|
154
|
-
self.fx = tuple(FX(self, i) for i in range(kind.num_fx))
|
|
155
|
-
self.fxsend = tuple(FXSend.make(self, i) for i in range(kind.num_fx))
|
|
156
|
-
self.fxreturn = tuple(FxRtn.make(self, i) for i in range(kind.num_fx))
|
|
157
|
-
self.auxreturn = AuxRtn.make(self)
|
|
158
|
-
self.config = Config.make(self)
|
|
159
|
-
self.headamp = tuple(HeadAmp(self, i) for i in range(kind.num_strip))
|
|
160
|
-
|
|
161
|
-
if kind.id_ == 'X32':
|
|
162
|
-
return type(
|
|
163
|
-
f'XAirRemote{kind}',
|
|
164
|
-
(XAirRemote,),
|
|
165
|
-
{
|
|
166
|
-
'__init__': init_x32,
|
|
167
|
-
},
|
|
168
|
-
)
|
|
169
|
-
return type(
|
|
170
|
-
f'XAirRemote{kind}',
|
|
171
|
-
(XAirRemote,),
|
|
172
|
-
{
|
|
173
|
-
'__init__': init_xair,
|
|
174
|
-
},
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
_remotes = {kind.id_: _make_remote(kind) for kind in kinds.all}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
def request_remote_obj(kind_id: str, *args, **kwargs) -> XAirRemote:
|
|
182
|
-
"""
|
|
183
|
-
Interface entry point. Wraps factory expression and handles errors
|
|
184
|
-
|
|
185
|
-
Returns a reference to an XAirRemote class of a kind
|
|
186
|
-
"""
|
|
187
|
-
|
|
188
|
-
XAIRREMOTE_cls = None
|
|
189
|
-
try:
|
|
190
|
-
XAIRREMOTE_cls = _remotes[kind_id]
|
|
191
|
-
except KeyError as e:
|
|
192
|
-
raise XAirRemoteError(f"Unknown mixer kind '{kind_id}'") from e
|
|
193
|
-
return XAIRREMOTE_cls(*args, **kwargs)
|
|
1
|
+
import abc
|
|
2
|
+
import logging
|
|
3
|
+
import threading
|
|
4
|
+
import time
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional, Union
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
import tomllib
|
|
10
|
+
except ModuleNotFoundError:
|
|
11
|
+
import tomli as tomllib
|
|
12
|
+
|
|
13
|
+
from pythonosc.dispatcher import Dispatcher
|
|
14
|
+
from pythonosc.osc_message_builder import OscMessageBuilder
|
|
15
|
+
from pythonosc.osc_server import BlockingOSCUDPServer
|
|
16
|
+
|
|
17
|
+
from . import adapter, kinds, util
|
|
18
|
+
from .bus import Bus
|
|
19
|
+
from .config import Config
|
|
20
|
+
from .dca import DCA
|
|
21
|
+
from .errors import XAirRemoteConnectionTimeoutError, XAirRemoteError
|
|
22
|
+
from .fx import FX, FXSend
|
|
23
|
+
from .headamp import HeadAmp
|
|
24
|
+
from .kinds import KindMap
|
|
25
|
+
from .lr import LR
|
|
26
|
+
from .rtn import AuxRtn, FxRtn
|
|
27
|
+
from .strip import Strip
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class OSCClientServer(BlockingOSCUDPServer):
|
|
33
|
+
def __init__(self, address: str, dispatcher: Dispatcher):
|
|
34
|
+
super().__init__(('', 0), dispatcher)
|
|
35
|
+
self.xr_address = address
|
|
36
|
+
|
|
37
|
+
def send_message(self, address: str, vals: Optional[Union[str, list]]):
|
|
38
|
+
builder = OscMessageBuilder(address=address)
|
|
39
|
+
vals = vals if vals is not None else []
|
|
40
|
+
if not isinstance(vals, list):
|
|
41
|
+
vals = [vals]
|
|
42
|
+
for val in vals:
|
|
43
|
+
builder.add_arg(val)
|
|
44
|
+
msg = builder.build()
|
|
45
|
+
self.socket.sendto(msg.dgram, self.xr_address)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class XAirRemote(abc.ABC):
|
|
49
|
+
"""Handles the communication with the mixer via the OSC protocol"""
|
|
50
|
+
|
|
51
|
+
_info_response = []
|
|
52
|
+
|
|
53
|
+
def __init__(self, **kwargs):
|
|
54
|
+
dispatcher = Dispatcher()
|
|
55
|
+
dispatcher.set_default_handler(self.msg_handler)
|
|
56
|
+
self.xair_ip = kwargs['ip'] or self._ip_from_toml()
|
|
57
|
+
self.xair_port = kwargs['port']
|
|
58
|
+
self._delay = kwargs['delay']
|
|
59
|
+
self.connect_timeout = kwargs['connect_timeout']
|
|
60
|
+
self.logger = logger.getChild(self.__class__.__name__)
|
|
61
|
+
if not self.xair_ip:
|
|
62
|
+
raise XAirRemoteError('No valid ip detected')
|
|
63
|
+
self.server = OSCClientServer((self.xair_ip, self.xair_port), dispatcher)
|
|
64
|
+
|
|
65
|
+
def __enter__(self):
|
|
66
|
+
self.worker = threading.Thread(target=self.run_server, daemon=True)
|
|
67
|
+
self.worker.start()
|
|
68
|
+
self.validate_connection()
|
|
69
|
+
return self
|
|
70
|
+
|
|
71
|
+
def _ip_from_toml(self) -> str:
|
|
72
|
+
filepath = Path.cwd() / 'config.toml'
|
|
73
|
+
with open(filepath, 'rb') as f:
|
|
74
|
+
conn = tomllib.load(f)
|
|
75
|
+
return conn['connection'].get('ip')
|
|
76
|
+
|
|
77
|
+
@util.timeout
|
|
78
|
+
def validate_connection(self):
|
|
79
|
+
if not self.query('/xinfo'):
|
|
80
|
+
raise XAirRemoteConnectionTimeoutError(self.xair_ip, self.xair_port)
|
|
81
|
+
self.logger.info(
|
|
82
|
+
f'Successfully connected to {self.info_response[2]} at {self.info_response[0]}.'
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def info_response(self):
|
|
87
|
+
return self._info_response
|
|
88
|
+
|
|
89
|
+
def run_server(self):
|
|
90
|
+
self.server.serve_forever()
|
|
91
|
+
|
|
92
|
+
def msg_handler(self, addr, *data):
|
|
93
|
+
self.logger.debug(f"received: {addr} {data if data else ''}")
|
|
94
|
+
self._info_response = data[:]
|
|
95
|
+
|
|
96
|
+
def send(self, addr: str, param: Optional[str] = None):
|
|
97
|
+
self.logger.debug(f"sending: {addr} {param if param is not None else ''}")
|
|
98
|
+
self.server.send_message(addr, param)
|
|
99
|
+
|
|
100
|
+
def query(self, address):
|
|
101
|
+
self.send(address)
|
|
102
|
+
time.sleep(self._delay)
|
|
103
|
+
return self.info_response
|
|
104
|
+
|
|
105
|
+
def __exit__(self, exc_type, exc_value, exc_tr):
|
|
106
|
+
self.server.shutdown()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _make_remote(kind: KindMap) -> XAirRemote:
|
|
110
|
+
"""
|
|
111
|
+
Creates a new XAIR remote class.
|
|
112
|
+
|
|
113
|
+
The returned class will subclass XAirRemote.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def init_x32(self, *args, **kwargs):
|
|
117
|
+
defaultkwargs = {
|
|
118
|
+
'ip': None,
|
|
119
|
+
'port': 10023,
|
|
120
|
+
'delay': 0.02,
|
|
121
|
+
'connect_timeout': 2,
|
|
122
|
+
}
|
|
123
|
+
kwargs = defaultkwargs | kwargs
|
|
124
|
+
XAirRemote.__init__(self, *args, **kwargs)
|
|
125
|
+
self.kind = kind
|
|
126
|
+
self.mainst = adapter.MainStereo.make(self)
|
|
127
|
+
self.mainmono = adapter.MainMono.make(self)
|
|
128
|
+
self.matrix = tuple(
|
|
129
|
+
adapter.Matrix.make(self, i) for i in range(kind.num_matrix)
|
|
130
|
+
)
|
|
131
|
+
self.strip = tuple(Strip.make(self, i) for i in range(kind.num_strip))
|
|
132
|
+
self.bus = tuple(adapter.Bus.make(self, i) for i in range(kind.num_bus))
|
|
133
|
+
self.dca = tuple(DCA(self, i) for i in range(kind.num_dca))
|
|
134
|
+
self.fx = tuple(FX(self, i) for i in range(kind.num_fx))
|
|
135
|
+
self.fxreturn = tuple(adapter.FxRtn.make(self, i) for i in range(kind.num_fx))
|
|
136
|
+
self.auxin = tuple(adapter.AuxRtn.make(self, i) for i in range(kind.num_auxrtn))
|
|
137
|
+
self.config = Config.make(self)
|
|
138
|
+
self.headamp = tuple(adapter.HeadAmp(self, i) for i in range(kind.num_headamp))
|
|
139
|
+
|
|
140
|
+
def init_xair(self, *args, **kwargs):
|
|
141
|
+
defaultkwargs = {
|
|
142
|
+
'ip': None,
|
|
143
|
+
'port': 10024,
|
|
144
|
+
'delay': 0.02,
|
|
145
|
+
'connect_timeout': 2,
|
|
146
|
+
}
|
|
147
|
+
kwargs = defaultkwargs | kwargs
|
|
148
|
+
XAirRemote.__init__(self, *args, **kwargs)
|
|
149
|
+
self.kind = kind
|
|
150
|
+
self.lr = LR.make(self)
|
|
151
|
+
self.strip = tuple(Strip.make(self, i) for i in range(kind.num_strip))
|
|
152
|
+
self.bus = tuple(Bus.make(self, i) for i in range(kind.num_bus))
|
|
153
|
+
self.dca = tuple(DCA(self, i) for i in range(kind.num_dca))
|
|
154
|
+
self.fx = tuple(FX(self, i) for i in range(kind.num_fx))
|
|
155
|
+
self.fxsend = tuple(FXSend.make(self, i) for i in range(kind.num_fx))
|
|
156
|
+
self.fxreturn = tuple(FxRtn.make(self, i) for i in range(kind.num_fx))
|
|
157
|
+
self.auxreturn = AuxRtn.make(self)
|
|
158
|
+
self.config = Config.make(self)
|
|
159
|
+
self.headamp = tuple(HeadAmp(self, i) for i in range(kind.num_strip))
|
|
160
|
+
|
|
161
|
+
if kind.id_ == 'X32':
|
|
162
|
+
return type(
|
|
163
|
+
f'XAirRemote{kind}',
|
|
164
|
+
(XAirRemote,),
|
|
165
|
+
{
|
|
166
|
+
'__init__': init_x32,
|
|
167
|
+
},
|
|
168
|
+
)
|
|
169
|
+
return type(
|
|
170
|
+
f'XAirRemote{kind}',
|
|
171
|
+
(XAirRemote,),
|
|
172
|
+
{
|
|
173
|
+
'__init__': init_xair,
|
|
174
|
+
},
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
_remotes = {kind.id_: _make_remote(kind) for kind in kinds.all}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def request_remote_obj(kind_id: str, *args, **kwargs) -> XAirRemote:
|
|
182
|
+
"""
|
|
183
|
+
Interface entry point. Wraps factory expression and handles errors
|
|
184
|
+
|
|
185
|
+
Returns a reference to an XAirRemote class of a kind
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
XAIRREMOTE_cls = None
|
|
189
|
+
try:
|
|
190
|
+
XAIRREMOTE_cls = _remotes[kind_id]
|
|
191
|
+
except KeyError as e:
|
|
192
|
+
raise XAirRemoteError(f"Unknown mixer kind '{kind_id}'") from e
|
|
193
|
+
return XAIRREMOTE_cls(*args, **kwargs)
|
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: xair-api
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.2
|
|
4
4
|
Summary: Remote control Behringer X-Air | Midas MR mixers through OSC
|
|
5
5
|
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Author: Onyx and Iris
|
|
7
8
|
Author-email: code@onyxandiris.online
|
|
8
|
-
Requires-Python:
|
|
9
|
+
Requires-Python: >=3.10
|
|
9
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
11
|
Classifier: Programming Language :: Python :: 3
|
|
11
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
17
|
Requires-Dist: python-osc (>=1.9.3,<2.0.0)
|
|
16
18
|
Requires-Dist: tomli (>=2.0.1,<3.0) ; python_version < "3.11"
|
|
17
19
|
Description-Content-Type: text/markdown
|
|
18
20
|
|
|
19
21
|
[](https://badge.fury.io/py/xair-api)
|
|
20
22
|
[](https://github.com/onyx-and-iris/xair-api-python/blob/dev/LICENSE)
|
|
23
|
+
[](https://python-poetry.org/)
|
|
21
24
|
[](https://github.com/astral-sh/ruff)
|
|
22
25
|

|
|
23
26
|
|
|
@@ -356,14 +359,14 @@ print(mixer.query('/ch/01/mix/on'))
|
|
|
356
359
|
|
|
357
360
|
### `Tests`
|
|
358
361
|
|
|
359
|
-
|
|
360
|
-
Save your current settings to a snapshot first.
|
|
362
|
+
Install [poetry](https://python-poetry.org/docs/#installation) and then:
|
|
361
363
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
364
|
+
```powershell
|
|
365
|
+
poetry poe test-xair
|
|
366
|
+
poetry poe test-x32
|
|
367
|
+
```
|
|
365
368
|
|
|
366
|
-
|
|
369
|
+
Unplug any expensive equipment and save your current settings to a snapshot first.
|
|
367
370
|
|
|
368
371
|
## License
|
|
369
372
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
xair_api/__init__.py,sha256=YM1f4GULAc-zea8hoUNRkLf8EVxEik_HY6F836-WxgM,70
|
|
2
|
+
xair_api/adapter.py,sha256=2OHM0ZzTYJTYjr0C4k5PNo24kkMy_w_zee_xLU7R0J8,916
|
|
3
|
+
xair_api/bus.py,sha256=4yjuk6ozwYqZRiuH8TS-TiV0-DwRiH7kQQXrjKZ7_Q0,1705
|
|
4
|
+
xair_api/config.py,sha256=fkVuOAVO69E1mtKnhKoiDaokEyWTAXk6qroOQ9yLWaA,5646
|
|
5
|
+
xair_api/dca.py,sha256=53CdLoYkJPlPQdIPzdJyN_MmFjNBSnjgRgMQCZcKcNs,1380
|
|
6
|
+
xair_api/errors.py,sha256=ljh0S9TiZFONQYXva_gMr3oxSKdlwIKV2NvU8nHQ79U,397
|
|
7
|
+
xair_api/fx.py,sha256=XbYud6WIYwDFq53lN2-Xfw0z7aY_z3PmGfqnAL4diPc,1737
|
|
8
|
+
xair_api/headamp.py,sha256=VJtkviBBIEg9gZWAFd3IkNwgqpz8jbS1UcUxMc06v24,1126
|
|
9
|
+
xair_api/kinds.py,sha256=w2NRvXySdPbdrMnVCW4lVluwvUibnNRcHOOKbP9bT0M,1094
|
|
10
|
+
xair_api/lr.py,sha256=nzcyKUKgBNGxs4XSoqAxlfNIY00mWdGBEfZEths5s8E,1721
|
|
11
|
+
xair_api/meta.py,sha256=rORjsY0GcZKqzr33kwhf6e5UM9_a1dS45J4T0sZLGX8,1489
|
|
12
|
+
xair_api/rtn.py,sha256=DIL6u0oYC5upVc13xdyqyN1Dn2bIRagg7D6DrnAJcPw,3065
|
|
13
|
+
xair_api/shared.py,sha256=LHJQeElMFfdHJLHZ6GVnFVCRuK69MRZpGtTKiPJN8eo,18544
|
|
14
|
+
xair_api/strip.py,sha256=O52_trXhZ6iOX3sRklkej-_AL-gAyYze08WL7ob3g20,2009
|
|
15
|
+
xair_api/util.py,sha256=_HyqmSiJ_kdBgHyBrdZI-3SmcQZMvX1GAUGwRavotA8,2169
|
|
16
|
+
xair_api/xair.py,sha256=Es_jg1bgW732S4fMGsMmuLVVNcg0DKFQRHoSQgooYC0,6389
|
|
17
|
+
xair_api-2.4.2.dist-info/METADATA,sha256=OQRmO0TcuuBMqf5e-wlbeV2K83HTDZah529-tkoTUqo,9075
|
|
18
|
+
xair_api-2.4.2.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
|
|
19
|
+
xair_api-2.4.2.dist-info/licenses/LICENSE,sha256=yqfnWf9m9ArjIqh56opp7LBgEjzkLeFK4xLfkPWrnus,1102
|
|
20
|
+
xair_api-2.4.2.dist-info/RECORD,,
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2018 Peter Dikant
|
|
4
|
-
Copyright (c) 2022 Onyx and Iris
|
|
5
|
-
|
|
6
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
-
in the Software without restriction, including without limitation the rights
|
|
9
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
-
furnished to do so, subject to the following conditions:
|
|
12
|
-
|
|
13
|
-
The above copyright notice and this permission notice shall be included in all
|
|
14
|
-
copies or substantial portions of the Software.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Peter Dikant
|
|
4
|
+
Copyright (c) 2022 Onyx and Iris
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
xair_api-2.4.1.dist-info/RECORD
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
xair_api/__init__.py,sha256=O6VVgrgm1hq2iwgl6XNAWu54uxlpr7aB28s_a6fCm10,73
|
|
2
|
-
xair_api/adapter.py,sha256=wD2oIFoHG-smgCC9z6fC_Ly0yIwjvZW5HPdjCT9KfLs,963
|
|
3
|
-
xair_api/bus.py,sha256=a44uaQ-OVxekKottir86aNzuP1Srw2s97Afshqq5m5o,1771
|
|
4
|
-
xair_api/config.py,sha256=vZ7R3eNu-it39icn1AlixAAFlp08ay3PXuNVQ725lzg,5853
|
|
5
|
-
xair_api/dca.py,sha256=sn_X9dK4i-DEPr8E8Ot9seYrIiL1bJiKSjiPmZ4FjBo,1443
|
|
6
|
-
xair_api/errors.py,sha256=Bm0ezXP8pgeiiz76UbVkaVpvJLw03qq71LOpCclaDEY,411
|
|
7
|
-
xair_api/fx.py,sha256=PxAX_XZE67XtnsPyp3xLH79-DeG6dVJZpjECDSB2Ltg,1811
|
|
8
|
-
xair_api/headamp.py,sha256=L6N5FrifYChUckuvOfp8fOrwczW9i1V51mXFowKaONk,1175
|
|
9
|
-
xair_api/kinds.py,sha256=WS3pZBgpGAG-HPIPkgOxnGqqTnqQAjOEAO6f5SD7FUY,1155
|
|
10
|
-
xair_api/lr.py,sha256=xqlsr2D_jvzDWsHDzbOf1EKW699UHd19vGmCFG6UQkk,1788
|
|
11
|
-
xair_api/meta.py,sha256=rU61YNScmiPcvlNU7WcAhRP9AQXS0XoOkZ9ntm1iW6k,1564
|
|
12
|
-
xair_api/rtn.py,sha256=f35eMrGw4YBfv1JK6vsKbaVXJfACotz8EycMxBiz2y4,3177
|
|
13
|
-
xair_api/shared.py,sha256=k1RuE2N_RR9nKQQa6AyeIqtZ4i6IfrKzSl4YM7eAC_4,19171
|
|
14
|
-
xair_api/strip.py,sha256=_ge_GfBeYiEBbRzMWBh67kaoZ907iwvnd6Bte_n_x9Y,2082
|
|
15
|
-
xair_api/util.py,sha256=OxgWTWRqZLUz4AGTRT-hETjM4EUO4e8tXppRSOFY01M,2263
|
|
16
|
-
xair_api/xair.py,sha256=Qhy7Ey6Gk092ADZNfn9sQ2sClRJHBZtehDBUNrUkRXQ,6582
|
|
17
|
-
xair_api-2.4.1.dist-info/LICENSE,sha256=m2fbtv9II-iQqimTd4zjgynL5vuEqGXauLSDJZycYIo,1124
|
|
18
|
-
xair_api-2.4.1.dist-info/METADATA,sha256=kc-8xB3c0997vgOl2YCEs33-je04tOmksS6uP6Uvx9s,8932
|
|
19
|
-
xair_api-2.4.1.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
20
|
-
xair_api-2.4.1.dist-info/RECORD,,
|