mirror of
https://github.com/onyx-and-iris/xair-api-python.git
synced 2026-04-07 16:43:32 +00:00
Compare commits
22 Commits
move-delay
...
add-module
| Author | SHA1 | Date | |
|---|---|---|---|
| 3a70a4c578 | |||
| 8b1b2c7f79 | |||
| 1e5e458105 | |||
| e05460e998 | |||
| d27824d1cf | |||
| 764195a452 | |||
| b295fee6e1 | |||
| 06be2f2831 | |||
| 2d0c0f91f0 | |||
| 6e017b4afc | |||
| 85664c8465 | |||
| a3473d5922 | |||
| e9ef113b5c | |||
| 56ec9a17c0 | |||
| 9a7d98d58b | |||
| f3cf215a76 | |||
| a62a46d61a | |||
| 5eeaff2371 | |||
| c2cf2fe523 | |||
| 265c26eb67 | |||
| 467b769ea4 | |||
| 27d0811091 |
101
CHANGELOG.md
101
CHANGELOG.md
@@ -9,18 +9,45 @@ Before any major/minor/patch bump all unit tests will be run to verify they pass
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
- [ ]
|
- [ ]
|
||||||
|
|
||||||
|
## [2.3.1] - 2024-02-15
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Module level loggers implemented
|
||||||
|
- class loggers are now child loggers
|
||||||
|
- Passing an incorrect kind_id to the entry point now raises an XAirRemoteError.
|
||||||
|
- Passing a value out of bounds to a setter now logs a warning instead of raising an exception.
|
||||||
|
- Send class added to README.
|
||||||
|
|
||||||
|
## [2.2.4] - 2024-02-14
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Send class mixed into Strip, AuxRtn, FxRtn. May now be accessed with {Class}.send
|
||||||
|
- Sends example added
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- delay kwarg now applies to getters. See [Issue #6](https://github.com/onyx-and-iris/xair-api-python/issues/6).
|
||||||
|
|
||||||
|
## [2.2.0] - 2022-11-08
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- mute prop to Bus, FX, LR, RTN, Strip classes.
|
||||||
|
|
||||||
## [2.1.0] - 2022-11-08
|
## [2.1.0] - 2022-11-08
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- delay keyword argument
|
- delay keyword argument
|
||||||
- bounds checks for vals passed to lin_set/log_set
|
- bounds checks for vals passed to lin_set/log_set
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- type checks, prefer duck typing
|
- type checks, prefer duck typing
|
||||||
|
|
||||||
## [2.0.0] - 2022-11-07
|
## [2.0.0] - 2022-11-07
|
||||||
|
|
||||||
@@ -29,76 +56,76 @@ However, a couple of changes have been made which are breaking, they are as foll
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- FX class added to fx module. This now deals with osc addresses that begin with "/fx/". Call it with mixer.fx.
|
- FX class added to fx module. This now deals with osc addresses that begin with "/fx/". Call it with mixer.fx.
|
||||||
- FxRtn class added to rtn module. This now deals with addresses that begin with "/rtn/". Call it with mixer.fxreturn
|
- FxRtn class added to rtn module. This now deals with addresses that begin with "/rtn/". Call it with mixer.fxreturn
|
||||||
- Aux class renamed to AuxRtn in rtn module. Call it with mixer.auxreturn.
|
- Aux class renamed to AuxRtn in rtn module. Call it with mixer.auxreturn.
|
||||||
|
|
||||||
These changes were made to better resemble the underlying osc api and to better describe the function of the classes.
|
These changes were made to better resemble the underlying osc api and to better describe the function of the classes.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- A small number of X32 tests. More will be added. XAir tests moved into it's own test module.
|
- A small number of X32 tests. More will be added. XAir tests moved into it's own test module.
|
||||||
- XAirRemote lower level section added to README.
|
- XAirRemote lower level section added to README.
|
||||||
- Links to OSC command documentation added to README.
|
- Links to OSC command documentation added to README.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- mixer.aux was renamed to mixer.auxreturn
|
- mixer.aux was renamed to mixer.auxreturn
|
||||||
|
|
||||||
## [1.1.0] - 2022-09-05
|
## [1.1.0] - 2022-09-05
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- tomli/tomllib compatibility layer to support python 3.10
|
- tomli/tomllib compatibility layer to support python 3.10
|
||||||
|
|
||||||
## [1.0.2] - 2022-08-07
|
## [1.0.2] - 2022-08-07
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- now packaged with poetry
|
- now packaged with poetry
|
||||||
- package added to pypi
|
- package added to pypi
|
||||||
- pypi, isort badges added to readme
|
- pypi, isort badges added to readme
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- package renamed to xair-api
|
- package renamed to xair-api
|
||||||
- now using tomllib for config, requires python 3.11
|
- now using tomllib for config, requires python 3.11
|
||||||
- readme, example updated.
|
- readme, example updated.
|
||||||
- imports isorted.
|
- imports isorted.
|
||||||
|
|
||||||
## [0.1.0] - 2022-05-01
|
## [0.1.0] - 2022-05-01
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- kind maps for "XR16", "XR12" added.
|
- kind maps for "XR16", "XR12" added.
|
||||||
- get() added to kind module.
|
- get() added to kind module.
|
||||||
- pre-commit.ps1 added for use with git hook.
|
- pre-commit.ps1 added for use with git hook.
|
||||||
- tests passed badge added to readme.
|
- tests passed badge added to readme.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- readme updated to reflect changes.
|
- readme updated to reflect changes.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- link to clone repo fixed in readme.
|
- link to clone repo fixed in readme.
|
||||||
- unit tests migrated from nose to pytest since nose will not be supported from python 3.10 onwards.
|
- unit tests migrated from nose to pytest since nose will not be supported from python 3.10 onwards.
|
||||||
|
|
||||||
## [0.0.1] - 2022-04-05
|
## [0.0.1] - 2022-04-05
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- \_query() added to base class, allows testing a single parameter.
|
- \_query() added to base class, allows testing a single parameter.
|
||||||
- Interface entry point defined.
|
- Interface entry point defined.
|
||||||
- Kind map for XR18/MR18 added
|
- Kind map for XR18/MR18 added
|
||||||
- Higher level classes (lr, strip, bus, fxsend, aux, rtn) implemented
|
- Higher level classes (lr, strip, bus, fxsend, aux, rtn) implemented
|
||||||
- Subclass mixin implemented (shared classes)
|
- Subclass mixin implemented (shared classes)
|
||||||
- meta module added
|
- meta module added
|
||||||
- util module added, mostly functions that perform math operations.
|
- util module added, mostly functions that perform math operations.
|
||||||
- readme initial commit.
|
- readme initial commit.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- base class now supports context manager.
|
- base class now supports context manager.
|
||||||
- load ip from ini
|
- load ip from ini
|
||||||
- unit tests initial commit. tests for shared classes added.
|
- unit tests initial commit. tests for shared classes added.
|
||||||
|
|||||||
188
README.md
188
README.md
@@ -12,7 +12,7 @@ For an outline of past/future changes refer to: [CHANGELOG](CHANGELOG.md)
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Python 3.10 or greater
|
- Python 3.10 or greater
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -59,19 +59,19 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
Currently the following devices are supported:
|
Currently the following devices are supported:
|
||||||
|
|
||||||
- `MR18`
|
- `MR18`
|
||||||
- `XR18`
|
- `XR18`
|
||||||
- `XR16`
|
- `XR16`
|
||||||
- `XR12`
|
- `XR12`
|
||||||
|
|
||||||
The `X32` is partially supported. However, this document covers specifically the `XAir` series.
|
The `X32` is partially supported. However, this document covers specifically the `XAir` series.
|
||||||
|
|
||||||
The following keyword arguments may be passed:
|
The following keyword arguments may be passed:
|
||||||
|
|
||||||
- `ip`: ip address of the mixer
|
- `ip`: ip address of the mixer
|
||||||
- `port`: mixer port, defaults to 10023 for x32 and 10024 for xair
|
- `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.
|
- a note about delay, stability may rely on network connection. For wired connections the delay can be safely reduced.
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ Contains the subclasses:
|
|||||||
### `Strip`
|
### `Strip`
|
||||||
|
|
||||||
Contains the subclasses:
|
Contains the subclasses:
|
||||||
(`Config`, `Preamp`, `Gate`, `Dyn`, `Insert`, `GEQ`, `EQ`, `Mix`, `Group`, `Automix`)
|
(`Config`, `Preamp`, `Gate`, `Dyn`, `Insert`, `GEQ`, `EQ`, `Mix`, `Group`, `Automix`, `Send`)
|
||||||
|
|
||||||
### `Bus`
|
### `Bus`
|
||||||
|
|
||||||
@@ -136,12 +136,12 @@ Contains the subclasses:
|
|||||||
### `FXRtn`
|
### `FXRtn`
|
||||||
|
|
||||||
Contains the subclasses:
|
Contains the subclasses:
|
||||||
(`Config`, `Preamp`, `EQ`, `Mix`, `Group`)
|
(`Config`, `Preamp`, `EQ`, `Mix`, `Group`, `Send`)
|
||||||
|
|
||||||
### `AuxRtn`
|
### `AuxRtn`
|
||||||
|
|
||||||
Contains the subclasses:
|
Contains the subclasses:
|
||||||
(`Config`, `Preamp`, `EQ`, `Mix`, `Group`)
|
(`Config`, `Preamp`, `EQ`, `Mix`, `Group`, `Send`)
|
||||||
|
|
||||||
### `Subclasses`
|
### `Subclasses`
|
||||||
|
|
||||||
@@ -149,134 +149,134 @@ For each subclass the corresponding properties are available.
|
|||||||
|
|
||||||
`Config`
|
`Config`
|
||||||
|
|
||||||
- `name`: string
|
- `name`: string
|
||||||
- `color`: int, from 0, 16
|
- `color`: int, from 0, 16
|
||||||
- `inputsource`: int
|
- `inputsource`: int
|
||||||
- `usbreturn`: int
|
- `usbreturn`: int
|
||||||
|
|
||||||
`Preamp`
|
`Preamp`
|
||||||
|
|
||||||
- `on`: bool
|
- `on`: bool
|
||||||
- `usbtrim`: float, from -18.0 to 18.0
|
- `usbtrim`: float, from -18.0 to 18.0
|
||||||
- `usbinput`: bool
|
- `usbinput`: bool
|
||||||
- `invert`: bool
|
- `invert`: bool
|
||||||
- `highpasson`: bool
|
- `highpasson`: bool
|
||||||
- `highpassfilter`: int, from 20 to 400
|
- `highpassfilter`: int, from 20 to 400
|
||||||
|
|
||||||
`Gate`
|
`Gate`
|
||||||
|
|
||||||
- `on`: bool
|
- `on`: bool
|
||||||
- `mode`: str, one of ('gate', 'exp2', 'exp3', 'exp4', 'duck')
|
- `mode`: str, one of ('gate', 'exp2', 'exp3', 'exp4', 'duck')
|
||||||
- `threshold`: float, from -80.0 to 0.0
|
- `threshold`: float, from -80.0 to 0.0
|
||||||
- `range`: int, from 3 to 60
|
- `range`: int, from 3 to 60
|
||||||
- `attack`: int, from 0 to 120
|
- `attack`: int, from 0 to 120
|
||||||
- `hold`: float, from 0.02 to 2000
|
- `hold`: float, from 0.02 to 2000
|
||||||
- `release`: int, from 5 to 4000
|
- `release`: int, from 5 to 4000
|
||||||
- `keysource`, from 0 to 22
|
- `keysource`, from 0 to 22
|
||||||
- `filteron`: bool
|
- `filteron`: bool
|
||||||
- `filtertype`: int, from 0 to 8
|
- `filtertype`: int, from 0 to 8
|
||||||
- `filterfreq`: float, from 20 to 20000
|
- `filterfreq`: float, from 20 to 20000
|
||||||
|
|
||||||
`Dyn`
|
`Dyn`
|
||||||
|
|
||||||
- `on`: bool
|
- `on`: bool
|
||||||
- `mode`: str, one of ('comp', 'exp')
|
- `mode`: str, one of ('comp', 'exp')
|
||||||
- `det`: str, one of ('peak', 'rms')
|
- `det`: str, one of ('peak', 'rms')
|
||||||
- `env`: str, one of ('lin', 'log')
|
- `env`: str, one of ('lin', 'log')
|
||||||
- `threshold`: float, from -60.0 to 0.0
|
- `threshold`: float, from -60.0 to 0.0
|
||||||
- `ratio`: int, from 0 to 11
|
- `ratio`: int, from 0 to 11
|
||||||
- `knee`: int, from 0 to 5
|
- `knee`: int, from 0 to 5
|
||||||
- `mgain`: float, from 0.0 to 24.0
|
- `mgain`: float, from 0.0 to 24.0
|
||||||
- `attack`: int, from 0 to 120
|
- `attack`: int, from 0 to 120
|
||||||
- `hold`: float, from 0.02 to 2000
|
- `hold`: float, from 0.02 to 2000
|
||||||
- `release`: int, from 5 to 4000
|
- `release`: int, from 5 to 4000
|
||||||
- `mix`: int, from 0 to 100
|
- `mix`: int, from 0 to 100
|
||||||
- `keysource`: int, from 0 to 22
|
- `keysource`: int, from 0 to 22
|
||||||
- `auto`: bool
|
- `auto`: bool
|
||||||
- `filteron`: bool
|
- `filteron`: bool
|
||||||
- `filtertype`: int, from 0 to 8
|
- `filtertype`: int, from 0 to 8
|
||||||
- `filterfreq`: float, from 20 to 20000
|
- `filterfreq`: float, from 20 to 20000
|
||||||
|
|
||||||
`Insert`
|
`Insert`
|
||||||
|
|
||||||
- `on`: bool
|
- `on`: bool
|
||||||
- `sel`: int
|
- `sel`: int
|
||||||
|
|
||||||
`GEQ`
|
`GEQ`
|
||||||
The following method names preceded by `slider_`
|
The following method names preceded by `slider_`
|
||||||
|
|
||||||
- `20`, `25`, `31_5`, `40`, `50`, `63`, `80`, `100`, `125`, `160`,
|
- `20`, `25`, `31_5`, `40`, `50`, `63`, `80`, `100`, `125`, `160`,
|
||||||
- `200`, `250`, `315`, `400`, `500`, `630`, `800`, `1k`, `1k25`, `1k6`, `2k`,
|
- `200`, `250`, `315`, `400`, `500`, `630`, `800`, `1k`, `1k25`, `1k6`, `2k`,
|
||||||
- `2k5`, `3k15`, `4k`, `5k`, `6k3`, `8k`, `10k`, `12k5`, `16k`, `20k`: float, from -15.0 to 15.0
|
- `2k5`, `3k15`, `4k`, `5k`, `6k3`, `8k`, `10k`, `12k5`, `16k`, `20k`: float, from -15.0 to 15.0
|
||||||
|
|
||||||
for example: `slider_20`, `slider_6k3` etc..
|
for example: `slider_20`, `slider_6k3` etc..
|
||||||
|
|
||||||
`EQ`
|
`EQ`
|
||||||
|
|
||||||
- `on`: bool
|
- `on`: bool
|
||||||
- `mode`: str, one of ('peq', 'geq', 'teq')
|
- `mode`: str, one of ('peq', 'geq', 'teq')
|
||||||
|
|
||||||
For the subclasses: `low`, `low2`, `lomid`, `himid`, `high2`, `high` the following properties are available:
|
For the subclasses: `low`, `low2`, `lomid`, `himid`, `high2`, `high` the following properties are available:
|
||||||
|
|
||||||
- `type`: int, from 0 to 5
|
- `type`: int, from 0 to 5
|
||||||
- `frequency`: float, from 20.0 to 20000.0
|
- `frequency`: float, from 20.0 to 20000.0
|
||||||
- `gain`: float, -15.0 to 15.0
|
- `gain`: float, -15.0 to 15.0
|
||||||
- `quality`: float, from 0.3 to 10.0
|
- `quality`: float, from 0.3 to 10.0
|
||||||
|
|
||||||
for example: `eq.low2.type`
|
for example: `eq.low2.type`
|
||||||
|
|
||||||
`Mix`
|
`Mix`
|
||||||
|
|
||||||
- `on`: bool
|
- `on`: bool
|
||||||
- `fader`: float, -inf, to 10.0
|
- `fader`: float, -inf, to 10.0
|
||||||
- `lr`: bool
|
- `lr`: bool
|
||||||
|
|
||||||
`Group`
|
`Group`
|
||||||
|
|
||||||
- `dca`: int, from 0 to 15
|
- `dca`: int, from 0 to 15
|
||||||
- `mute`: int, from 0 to 15
|
- `mute`: int, from 0 to 15
|
||||||
|
|
||||||
`Automix`
|
`Automix`
|
||||||
|
|
||||||
- `group`: int, from 0 to 2
|
- `group`: int, from 0 to 2
|
||||||
- `weight`: float, from -12.0 to 12.0
|
- `weight`: float, from -12.0 to 12.0
|
||||||
|
|
||||||
### `DCA`
|
### `DCA`
|
||||||
|
|
||||||
- `on`: bool
|
- `on`: bool
|
||||||
- `name`: str
|
- `name`: str
|
||||||
- `color`: int, from 0 to 15
|
- `color`: int, from 0 to 15
|
||||||
|
|
||||||
### `Config`
|
### `Config`
|
||||||
|
|
||||||
The following method names preceded by `chlink`
|
The following method names preceded by `chlink`
|
||||||
|
|
||||||
- `1_2`, `3_4`, `5_6`, `7_8`, `9_10`, `11_12`, `13_14`, `15_16`
|
- `1_2`, `3_4`, `5_6`, `7_8`, `9_10`, `11_12`, `13_14`, `15_16`
|
||||||
|
|
||||||
The following method names preceded by `buslink`
|
The following method names preceded by `buslink`
|
||||||
|
|
||||||
- `1_2`, `3_4`, `5_6`
|
- `1_2`, `3_4`, `5_6`
|
||||||
|
|
||||||
for example: `chlink1_2`, `buslink5_6` etc..
|
for example: `chlink1_2`, `buslink5_6` etc..
|
||||||
|
|
||||||
- `link_eq`: bool
|
- `link_eq`: bool
|
||||||
- `link_dyn`: bool
|
- `link_dyn`: bool
|
||||||
- `link_fader_mute`: bool
|
- `link_fader_mute`: bool
|
||||||
- `amixenable`: bool
|
- `amixenable`: bool
|
||||||
- `amixlock`: bool
|
- `amixlock`: bool
|
||||||
|
|
||||||
For the subclass `monitor` the following properties are available
|
For the subclass `monitor` the following properties are available
|
||||||
|
|
||||||
- `level`: float, -inf to 10.0
|
- `level`: float, -inf to 10.0
|
||||||
- `source`: int, from 0 to 14
|
- `source`: int, from 0 to 14
|
||||||
- `sourcetrim`: float, from -18.0 to 18.0
|
- `sourcetrim`: float, from -18.0 to 18.0
|
||||||
- `chmode`: bool
|
- `chmode`: bool
|
||||||
- `busmode`: bool
|
- `busmode`: bool
|
||||||
- `dim`: bool
|
- `dim`: bool
|
||||||
- `dimgain`: float, from -40.0 to 0.0
|
- `dimgain`: float, from -40.0 to 0.0
|
||||||
- `mono`: bool
|
- `mono`: bool
|
||||||
- `mute`: bool
|
- `mute`: bool
|
||||||
- `dimfpl`: bool
|
- `dimfpl`: bool
|
||||||
|
|
||||||
for example: `config.monitor.chmode`
|
for example: `config.monitor.chmode`
|
||||||
|
|
||||||
@@ -284,15 +284,21 @@ for example: `config.monitor.chmode`
|
|||||||
|
|
||||||
tuple containing a class for each mute group
|
tuple containing a class for each mute group
|
||||||
|
|
||||||
- `on`: bool, from 0 to 3
|
- `on`: bool, from 0 to 3
|
||||||
|
|
||||||
for example: `config.mute_group[0].on = True`
|
for example: `config.mute_group[0].on = True`
|
||||||
|
|
||||||
|
### `Send`
|
||||||
|
|
||||||
|
- `level`: float, -inf to 10.0
|
||||||
|
|
||||||
|
for example: `mixer.strip[10].send[3].level = -16.5`
|
||||||
|
|
||||||
### XAirRemote class (lower level)
|
### XAirRemote class (lower level)
|
||||||
|
|
||||||
Send an OSC command directly to the mixer
|
Send an OSC command directly to the mixer
|
||||||
|
|
||||||
- `send(osc command, value)`
|
- `send(osc command, value)`
|
||||||
|
|
||||||
for example:
|
for example:
|
||||||
|
|
||||||
@@ -303,7 +309,7 @@ mixer.send("/bus/2/config/name", "somename")
|
|||||||
|
|
||||||
Query the value of a command:
|
Query the value of a command:
|
||||||
|
|
||||||
- `query(osc command)`
|
- `query(osc command)`
|
||||||
|
|
||||||
for example:
|
for example:
|
||||||
|
|
||||||
|
|||||||
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 obsws_python as obs
|
||||||
|
|
||||||
import xair_api
|
import xair_api
|
||||||
|
|
||||||
|
|
||||||
class Observer:
|
class Observer:
|
||||||
def __init__(self, mixer):
|
def __init__(self, mixer):
|
||||||
self._mixer = mixer
|
self._mixer = mixer
|
||||||
self._cl = obs.EventClient()
|
self._client = obs.EventClient()
|
||||||
self._cl.callback.register(self.on_current_program_scene_changed)
|
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):
|
def on_current_program_scene_changed(self, data):
|
||||||
scene = data.scene_name
|
scene = data.scene_name
|
||||||
@@ -28,11 +35,9 @@ class Observer:
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
with xair_api.connect("MR18", ip="mixer.local") as mixer:
|
with xair_api.connect("MR18", ip="mixer.local") as mixer:
|
||||||
Observer(mixer)
|
with Observer(mixer):
|
||||||
|
while _ := input("Press <Enter> to exit\n"):
|
||||||
while cmd := input("<Enter> to exit\n"):
|
pass
|
||||||
if not cmd:
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "xair-api"
|
name = "xair-api"
|
||||||
version = "2.2.3"
|
version = "2.3.1"
|
||||||
description = "Remote control Behringer X-Air | Midas MR mixers through OSC"
|
description = "Remote control Behringer X-Air | Midas MR mixers through OSC"
|
||||||
authors = ["onyx-and-iris <code@onyxandiris.online>"]
|
authors = ["onyx-and-iris <code@onyxandiris.online>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
@@ -24,5 +24,6 @@ build-backend = "poetry.core.masonry.api"
|
|||||||
|
|
||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
obs = "scripts:ex_obs"
|
obs = "scripts:ex_obs"
|
||||||
|
sends = "scripts:ex_sends"
|
||||||
xair = "scripts:test_xair"
|
xair = "scripts:test_xair"
|
||||||
x32 = "scripts:test_x32"
|
x32 = "scripts:test_x32"
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
def ex_obs():
|
def ex_obs():
|
||||||
path = Path.cwd() / "examples" / "xair_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():
|
def test_xair():
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ class FxRtn(IFxRtn):
|
|||||||
class MainStereo(ILR):
|
class MainStereo(ILR):
|
||||||
@property
|
@property
|
||||||
def address(self) -> str:
|
def address(self) -> str:
|
||||||
return f"/main/st"
|
return "/main/st"
|
||||||
|
|
||||||
|
|
||||||
class MainMono(ILR):
|
class MainMono(ILR):
|
||||||
@property
|
@property
|
||||||
def address(self) -> str:
|
def address(self) -> str:
|
||||||
return f"/main/m"
|
return "/main/m"
|
||||||
|
|
||||||
|
|
||||||
class Matrix(ILR):
|
class Matrix(ILR):
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import abc
|
import abc
|
||||||
|
import logging
|
||||||
|
|
||||||
from .errors import XAirRemoteError
|
|
||||||
from .meta import mute_prop
|
from .meta import mute_prop
|
||||||
from .shared import EQ, GEQ, Automix, Config, Dyn, Gate, Group, Insert, Mix, Preamp
|
from .shared import EQ, GEQ, Config, Dyn, Group, Insert, Mix
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IBus(abc.ABC):
|
class IBus(abc.ABC):
|
||||||
@@ -11,6 +13,7 @@ class IBus(abc.ABC):
|
|||||||
def __init__(self, remote, index: int):
|
def __init__(self, remote, index: int):
|
||||||
self._remote = remote
|
self._remote = remote
|
||||||
self.index = index + 1
|
self.index = index + 1
|
||||||
|
self.logger = logger.getChild(self.__class__.__name__)
|
||||||
|
|
||||||
def getter(self, param: str):
|
def getter(self, param: str):
|
||||||
return self._remote.query(f"{self.address}/{param}")
|
return self._remote.query(f"{self.address}/{param}")
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import abc
|
import abc
|
||||||
|
import logging
|
||||||
|
|
||||||
from . import kinds
|
from . import kinds, util
|
||||||
from .errors import XAirRemoteError
|
|
||||||
from .meta import bool_prop
|
from .meta import bool_prop
|
||||||
from .util import _get_level_val, _set_level_val, lin_get, lin_set
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IConfig(abc.ABC):
|
class IConfig(abc.ABC):
|
||||||
@@ -11,6 +12,7 @@ class IConfig(abc.ABC):
|
|||||||
|
|
||||||
def __init__(self, remote):
|
def __init__(self, remote):
|
||||||
self._remote = remote
|
self._remote = remote
|
||||||
|
self.logger = logger.getChild(self.__class__.__name__)
|
||||||
|
|
||||||
def getter(self, param: str):
|
def getter(self, param: str):
|
||||||
return self._remote.query(f"{self.address}/{param}")
|
return self._remote.query(f"{self.address}/{param}")
|
||||||
@@ -34,8 +36,8 @@ class Config(IConfig):
|
|||||||
Returns a Config class of a kind.
|
Returns a Config class of a kind.
|
||||||
"""
|
"""
|
||||||
LINKS_cls = _make_links_mixins[remote.kind.id_]
|
LINKS_cls = _make_links_mixins[remote.kind.id_]
|
||||||
MUTEGROUP_cls = type(f"MuteGroup", (Config.MuteGroup, cls), {})
|
MUTEGROUP_cls = type("MuteGroup", (Config.MuteGroup, cls), {})
|
||||||
MONITOR_cls = type(f"ConfigMonitor", (Config.Monitor, cls), {})
|
MONITOR_cls = type("ConfigMonitor", (Config.Monitor, cls), {})
|
||||||
CONFIG_cls = type(
|
CONFIG_cls = type(
|
||||||
f"Config{remote.kind}",
|
f"Config{remote.kind}",
|
||||||
(cls, LINKS_cls),
|
(cls, LINKS_cls),
|
||||||
@@ -48,7 +50,7 @@ class Config(IConfig):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def address(self) -> str:
|
def address(self) -> str:
|
||||||
return f"/config"
|
return "/config"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def amixenable(self) -> bool:
|
def amixenable(self) -> bool:
|
||||||
@@ -91,13 +93,14 @@ class Config(IConfig):
|
|||||||
return f"{root}/solo"
|
return f"{root}/solo"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@util.db_from
|
||||||
def level(self) -> float:
|
def level(self) -> float:
|
||||||
retval = self.getter("level")[0]
|
return self.getter("level")[0]
|
||||||
return _get_level_val(retval)
|
|
||||||
|
|
||||||
@level.setter
|
@level.setter
|
||||||
|
@util.db_to
|
||||||
def level(self, val: float):
|
def level(self, val: float):
|
||||||
_set_level_val(self, val)
|
self.setter("level", val)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def source(self) -> int:
|
def source(self) -> int:
|
||||||
@@ -105,17 +108,19 @@ class Config(IConfig):
|
|||||||
|
|
||||||
@source.setter
|
@source.setter
|
||||||
def source(self, val: int):
|
def source(self, val: int):
|
||||||
self.setter(f"source", val)
|
self.setter("source", val)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def sourcetrim(self) -> float:
|
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
|
@sourcetrim.setter
|
||||||
def sourcetrim(self, val: float):
|
def sourcetrim(self, val: float):
|
||||||
if not -18 <= val <= 18:
|
if not -18 <= val <= 18:
|
||||||
raise XAirRemoteError("expected value in range -18.0 to 18.0")
|
self.logger.warning(
|
||||||
self.setter("sourcetrim", lin_set(-18, 18, val))
|
f"sourcetrim got {val}, expected value in range -18.0 to 18.0"
|
||||||
|
)
|
||||||
|
self.setter("sourcetrim", util.lin_set(-18, 18, val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def chmode(self) -> bool:
|
def chmode(self) -> bool:
|
||||||
@@ -135,13 +140,15 @@ class Config(IConfig):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def dimgain(self) -> int:
|
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
|
@dimgain.setter
|
||||||
def dimgain(self, val: int):
|
def dimgain(self, val: int):
|
||||||
if not -40 <= val <= 0:
|
if not -40 <= val <= 0:
|
||||||
raise XAirRemoteError("expected value in range -40 to 0")
|
self.logger.warning(
|
||||||
self.setter("dimatt", lin_set(-40, 0, val))
|
f"dimgain got {val}, expected value in range -40 to 0"
|
||||||
|
)
|
||||||
|
self.setter("dimatt", util.lin_set(-40, 0, val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dim(self) -> bool:
|
def dim(self) -> bool:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import abc
|
import abc
|
||||||
|
import logging
|
||||||
|
|
||||||
from .errors import XAirRemoteError
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IDCA(abc.ABC):
|
class IDCA(abc.ABC):
|
||||||
@@ -9,6 +10,7 @@ class IDCA(abc.ABC):
|
|||||||
def __init__(self, remote, index: int):
|
def __init__(self, remote, index: int):
|
||||||
self._remote = remote
|
self._remote = remote
|
||||||
self.index = index + 1
|
self.index = index + 1
|
||||||
|
self.logger = logger.getChild(self.__class__.__name__)
|
||||||
|
|
||||||
def getter(self, param: str) -> tuple:
|
def getter(self, param: str) -> tuple:
|
||||||
return self._remote.query(f"{self.address}/{param}")
|
return self._remote.query(f"{self.address}/{param}")
|
||||||
@@ -50,7 +52,7 @@ class DCA(IDCA):
|
|||||||
|
|
||||||
@name.setter
|
@name.setter
|
||||||
def name(self, val: str):
|
def name(self, val: str):
|
||||||
self.setter("config/name")[0]
|
self.setter("config/name", val)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def color(self) -> int:
|
def color(self) -> int:
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
class XAirRemoteError(Exception):
|
class XAirRemoteError(Exception):
|
||||||
"""Base error class for XAIR Remote."""
|
"""Base error class for XAIR Remote."""
|
||||||
|
|
||||||
pass
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import abc
|
import abc
|
||||||
|
import logging
|
||||||
|
|
||||||
from .errors import XAirRemoteError
|
|
||||||
from .meta import mute_prop
|
from .meta import mute_prop
|
||||||
from .shared import EQ, GEQ, Automix, Config, Dyn, Gate, Group, Insert, Mix, Preamp
|
from .shared import Config, Group, Mix
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IFX(abc.ABC):
|
class IFX(abc.ABC):
|
||||||
@@ -11,6 +13,7 @@ class IFX(abc.ABC):
|
|||||||
def __init__(self, remote, index: int):
|
def __init__(self, remote, index: int):
|
||||||
self._remote = remote
|
self._remote = remote
|
||||||
self.index = index + 1
|
self.index = index + 1
|
||||||
|
self.logger = logger.getChild(self.__class__.__name__)
|
||||||
|
|
||||||
def getter(self, param: str):
|
def getter(self, param: str):
|
||||||
return self._remote.query(f"{self.address}/{param}")
|
return self._remote.query(f"{self.address}/{param}")
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
import abc
|
import abc
|
||||||
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .errors import XAirRemoteError
|
|
||||||
from .meta import mute_prop
|
from .meta import mute_prop
|
||||||
from .shared import EQ, GEQ, Automix, Config, Dyn, Gate, Group, Insert, Mix, Preamp
|
from .shared import EQ, GEQ, Config, Dyn, Insert, Mix
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ILR(abc.ABC):
|
class ILR(abc.ABC):
|
||||||
"""Abstract Base Class for buses"""
|
"""Abstract Base Class for lr"""
|
||||||
|
|
||||||
def __init__(self, remote, index: Optional[int] = None):
|
def __init__(self, remote, index: Optional[int] = None):
|
||||||
self._remote = remote
|
self._remote = remote
|
||||||
if index is not None:
|
if index is not None:
|
||||||
self.index = index + 1
|
self.index = index + 1
|
||||||
|
self.logger = logger.getChild(self.__class__.__name__)
|
||||||
|
|
||||||
def getter(self, param: str):
|
def getter(self, param: str):
|
||||||
return self._remote.query(f"{self.address}/{param}")
|
return self._remote.query(f"{self.address}/{param}")
|
||||||
@@ -26,7 +29,7 @@ class ILR(abc.ABC):
|
|||||||
|
|
||||||
|
|
||||||
class LR(ILR):
|
class LR(ILR):
|
||||||
"""Concrete class for buses"""
|
"""Concrete class for lr"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def make(cls, remote, index=None):
|
def make(cls, remote, index=None):
|
||||||
@@ -61,4 +64,4 @@ class LR(ILR):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def address(self) -> str:
|
def address(self) -> str:
|
||||||
return f"/lr"
|
return "/lr"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
from .errors import XAirRemoteError
|
|
||||||
from .util import lin_get, lin_set
|
from .util import lin_get, lin_set
|
||||||
|
|
||||||
|
|
||||||
@@ -51,13 +50,6 @@ def float_prop(param):
|
|||||||
|
|
||||||
|
|
||||||
def geq_prop(param):
|
def geq_prop(param):
|
||||||
# fmt: off
|
|
||||||
opts = {
|
|
||||||
"1k": 1000, "1k25": 1250, "1k6": 1600, "2k": 2000, "3k15": 3150, "4k": 4000,
|
|
||||||
"5k": 5000, "6k3": 6300, "8k": 8000, "10k": 10000, "12k5": 12500, "16k": 16000,
|
|
||||||
"20k": 20000,
|
|
||||||
}
|
|
||||||
# fmt: on
|
|
||||||
param = param.replace("_", ".")
|
param = param.replace("_", ".")
|
||||||
|
|
||||||
def fget(self) -> float:
|
def fget(self) -> float:
|
||||||
@@ -65,7 +57,9 @@ def geq_prop(param):
|
|||||||
|
|
||||||
def fset(self, val):
|
def fset(self, val):
|
||||||
if not -15 <= val <= 15:
|
if not -15 <= val <= 15:
|
||||||
raise XAirRemoteError("expected value in range -15.0 to 15.0")
|
self.logger.warning(
|
||||||
|
f"slider_{param} got {val}, expected value in range -15.0 to 15.0"
|
||||||
|
)
|
||||||
self.setter(param, lin_set(-15, 15, val))
|
self.setter(param, lin_set(-15, 15, val))
|
||||||
|
|
||||||
return property(fget, fset)
|
return property(fget, fset)
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
import abc
|
import abc
|
||||||
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .errors import XAirRemoteError
|
|
||||||
from .meta import mute_prop
|
from .meta import mute_prop
|
||||||
from .shared import EQ, GEQ, Automix, Config, Dyn, Gate, Group, Insert, Mix, Preamp
|
from .shared import EQ, Config, Group, Mix, Preamp, Send
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IRtn(abc.ABC):
|
class IRtn(abc.ABC):
|
||||||
"""Abstract Base Class for aux"""
|
"""Abstract Base Class for rtn"""
|
||||||
|
|
||||||
def __init__(self, remote, index: Optional[int] = None):
|
def __init__(self, remote, index: Optional[int] = None):
|
||||||
self._remote = remote
|
self._remote = remote
|
||||||
if index is not None:
|
if index is not None:
|
||||||
self.index = index + 1
|
self.index = index + 1
|
||||||
|
self.logger = logger.getChild(self.__class__.__name__)
|
||||||
|
|
||||||
def getter(self, param: str):
|
def getter(self, param: str):
|
||||||
return self._remote.query(f"{self.address}/{param}")
|
return self._remote.query(f"{self.address}/{param}")
|
||||||
@@ -26,13 +29,15 @@ class IRtn(abc.ABC):
|
|||||||
|
|
||||||
|
|
||||||
class AuxRtn(IRtn):
|
class AuxRtn(IRtn):
|
||||||
"""Concrete class for aux"""
|
"""Concrete class for auxrtn"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def make(cls, remote, index=None):
|
def make(cls, remote, index=None):
|
||||||
"""
|
"""
|
||||||
Factory function for auxrtn
|
Factory function for auxrtn
|
||||||
|
|
||||||
Creates a mixin of shared subclasses, sets them as class attributes.
|
Creates a mixin of shared subclasses, sets them as class attributes.
|
||||||
|
|
||||||
Returns an AuxRtn class of a kind.
|
Returns an AuxRtn class of a kind.
|
||||||
"""
|
"""
|
||||||
AUXRTN_cls = type(
|
AUXRTN_cls = type(
|
||||||
@@ -51,6 +56,10 @@ class AuxRtn(IRtn):
|
|||||||
Group,
|
Group,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
"send": tuple(
|
||||||
|
Send.make(cls, i, remote)
|
||||||
|
for i in range(remote.kind.num_bus + remote.kind.num_fx)
|
||||||
|
),
|
||||||
"mute": mute_prop(),
|
"mute": mute_prop(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -62,13 +71,15 @@ class AuxRtn(IRtn):
|
|||||||
|
|
||||||
|
|
||||||
class FxRtn(IRtn):
|
class FxRtn(IRtn):
|
||||||
"""Concrete class for rtn"""
|
"""Concrete class for fxrtn"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def make(cls, remote, index):
|
def make(cls, remote, index):
|
||||||
"""
|
"""
|
||||||
Factory function for fxrtn
|
Factory function for fxrtn
|
||||||
|
|
||||||
Creates a mixin of shared subclasses, sets them as class attributes.
|
Creates a mixin of shared subclasses, sets them as class attributes.
|
||||||
|
|
||||||
Returns an FxRtn class of a kind.
|
Returns an FxRtn class of a kind.
|
||||||
"""
|
"""
|
||||||
FXRTN_cls = type(
|
FXRTN_cls = type(
|
||||||
@@ -87,6 +98,10 @@ class FxRtn(IRtn):
|
|||||||
Group,
|
Group,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
"send": tuple(
|
||||||
|
Send.make(cls, i, remote, index)
|
||||||
|
for i in range(remote.kind.num_bus + remote.kind.num_fx)
|
||||||
|
),
|
||||||
"mute": mute_prop(),
|
"mute": mute_prop(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
from typing import Union
|
from typing import Optional, Union
|
||||||
|
|
||||||
from .errors import XAirRemoteError
|
from . import util
|
||||||
from .meta import geq_prop
|
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
|
Classes shared by /ch, /rtn, /rtn/aux, /bus, /fxsend, /lr
|
||||||
@@ -56,13 +55,15 @@ class Preamp:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def usbtrim(self) -> float:
|
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
|
@usbtrim.setter
|
||||||
def usbtrim(self, val: float):
|
def usbtrim(self, val: float):
|
||||||
if not -18 <= val <= 18:
|
if not -18 <= val <= 18:
|
||||||
raise XAirRemoteError("expected value in range -18.0 to 18.0")
|
self.logger.warning(
|
||||||
self.setter("rtntrim", lin_set(-18, 18, val))
|
f"usbtrim got {val}, expected value in range -18.0 to 18.0"
|
||||||
|
)
|
||||||
|
self.setter("rtntrim", util.lin_set(-18, 18, val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def usbinput(self) -> bool:
|
def usbinput(self) -> bool:
|
||||||
@@ -90,13 +91,15 @@ class Preamp:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def highpassfilter(self) -> int:
|
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
|
@highpassfilter.setter
|
||||||
def highpassfilter(self, val: int):
|
def highpassfilter(self, val: int):
|
||||||
if not 20 <= val <= 400:
|
if not 20 <= val <= 400:
|
||||||
raise XAirRemoteError("expected value in range 20 to 400")
|
self.logger.warning(
|
||||||
self.setter("hpf", log_set(20, 400, val))
|
f"highpassfilter got {val}, expected value in range 20 to 400"
|
||||||
|
)
|
||||||
|
self.setter("hpf", util.log_set(20, 400, val))
|
||||||
|
|
||||||
|
|
||||||
class Gate:
|
class Gate:
|
||||||
@@ -122,59 +125,63 @@ class Gate:
|
|||||||
def mode(self, val: str):
|
def mode(self, val: str):
|
||||||
opts = ("gate", "exp2", "exp3", "exp4", "duck")
|
opts = ("gate", "exp2", "exp3", "exp4", "duck")
|
||||||
if val not in opts:
|
if val not in opts:
|
||||||
raise XAirRemoteError(f"expected one of {opts}")
|
self.logger.warning(f"mode got {val}, expected one of {opts}")
|
||||||
self.setter("mode", opts.index(val))
|
self.setter("mode", opts.index(val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def threshold(self) -> float:
|
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
|
@threshold.setter
|
||||||
def threshold(self, val: float):
|
def threshold(self, val: float):
|
||||||
if not -80 <= val <= 0:
|
if not -80 <= val <= 0:
|
||||||
raise XAirRemoteError("expected value in range -80.0 to 0.0")
|
self.logger.warning(
|
||||||
self.setter("thr", lin_set(-80, 0, val))
|
f"threshold got {val}, expected value in range -80.0 to 0.0"
|
||||||
|
)
|
||||||
|
self.setter("thr", util.lin_set(-80, 0, val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def range(self) -> int:
|
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
|
@range.setter
|
||||||
def range(self, val: int):
|
def range(self, val: int):
|
||||||
if not 3 <= val <= 60:
|
if not 3 <= val <= 60:
|
||||||
raise XAirRemoteError("expected value in range 3 to 60")
|
self.logger.warning(f"range got {val}, 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
|
@property
|
||||||
def attack(self) -> int:
|
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
|
@attack.setter
|
||||||
def attack(self, val: int):
|
def attack(self, val: int):
|
||||||
if not 0 <= val <= 120:
|
if not 0 <= val <= 120:
|
||||||
raise XAirRemoteError("expected value in range 0 to 120")
|
self.logger.warning(f"attack got {val}, 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
|
@property
|
||||||
def hold(self) -> Union[float, int]:
|
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)
|
return round(val, 1) if val < 100 else int(val)
|
||||||
|
|
||||||
@hold.setter
|
@hold.setter
|
||||||
def hold(self, val: float):
|
def hold(self, val: float):
|
||||||
if not 0.02 <= val <= 2000:
|
if not 0.02 <= val <= 2000:
|
||||||
raise XAirRemoteError("expected value in range 0.02 to 2000.0")
|
self.logger.warning(
|
||||||
self.setter("hold", log_set(0.02, 2000, val))
|
f"hold got {val}, expected value in range 0.02 to 2000.0"
|
||||||
|
)
|
||||||
|
self.setter("hold", util.log_set(0.02, 2000, val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def release(self) -> int:
|
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
|
@release.setter
|
||||||
def release(self, val: int):
|
def release(self, val: int):
|
||||||
if not 5 <= val <= 4000:
|
if not 5 <= val <= 4000:
|
||||||
raise XAirRemoteError("expected value in range 5 to 4000")
|
self.logger.warning(f"release got {val}, 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
|
@property
|
||||||
def keysource(self):
|
def keysource(self):
|
||||||
@@ -202,14 +209,16 @@ class Gate:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def filterfreq(self) -> Union[float, int]:
|
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)
|
return int(retval) if retval > 1000 else round(retval, 1)
|
||||||
|
|
||||||
@filterfreq.setter
|
@filterfreq.setter
|
||||||
def filterfreq(self, val: Union[float, int]):
|
def filterfreq(self, val: Union[float, int]):
|
||||||
if not 20 <= val <= 20000:
|
if not 20 <= val <= 20000:
|
||||||
raise XAirRemoteError("expected value in range 20 to 20000")
|
self.logger.warning(
|
||||||
self.setter("filter/f", log_set(20, 20000, val))
|
f"filterfreq got {val}, expected value in range 20 to 20000"
|
||||||
|
)
|
||||||
|
self.setter("filter/f", util.log_set(20, 20000, val))
|
||||||
|
|
||||||
|
|
||||||
class Dyn:
|
class Dyn:
|
||||||
@@ -235,7 +244,7 @@ class Dyn:
|
|||||||
def mode(self, val: str):
|
def mode(self, val: str):
|
||||||
opts = ("comp", "exp")
|
opts = ("comp", "exp")
|
||||||
if val not in opts:
|
if val not in opts:
|
||||||
raise XAirRemoteError(f"expected one of {opts}")
|
self.logger.warning(f"mode got {val}, expected one of {opts}")
|
||||||
self.setter("mode", opts.index(val))
|
self.setter("mode", opts.index(val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -247,7 +256,7 @@ class Dyn:
|
|||||||
def det(self, val: str):
|
def det(self, val: str):
|
||||||
opts = ("peak", "rms")
|
opts = ("peak", "rms")
|
||||||
if val not in opts:
|
if val not in opts:
|
||||||
raise XAirRemoteError(f"expected one of {opts}")
|
self.logger.warning(f"det got {val}, expected one of {opts}")
|
||||||
self.setter("det", opts.index(val))
|
self.setter("det", opts.index(val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -259,18 +268,20 @@ class Dyn:
|
|||||||
def env(self, val: str):
|
def env(self, val: str):
|
||||||
opts = ("lin", "log")
|
opts = ("lin", "log")
|
||||||
if val not in opts:
|
if val not in opts:
|
||||||
raise XAirRemoteError(f"expected one of {opts}")
|
self.logger.warning(f"env got {val}, expected one of {opts}")
|
||||||
self.setter("env", opts.index(val))
|
self.setter("env", opts.index(val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def threshold(self) -> float:
|
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
|
@threshold.setter
|
||||||
def threshold(self, val: float):
|
def threshold(self, val: float):
|
||||||
if not -60 <= val <= 0:
|
if not -60 <= val <= 0:
|
||||||
raise XAirRemoteError("expected value in range -60.0 to 0")
|
self.logger.warning(
|
||||||
self.setter("thr", lin_set(-60, 0, val))
|
f"threshold got {val}, expected value in range -60.0 to 0"
|
||||||
|
)
|
||||||
|
self.setter("thr", util.lin_set(-60, 0, val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ratio(self) -> Union[float, int]:
|
def ratio(self) -> Union[float, int]:
|
||||||
@@ -283,64 +294,66 @@ class Dyn:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def knee(self) -> int:
|
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
|
@knee.setter
|
||||||
def knee(self, val: int):
|
def knee(self, val: int):
|
||||||
if not 0 <= val <= 5:
|
if not 0 <= val <= 5:
|
||||||
raise XAirRemoteError("expected value in range 0 to 5")
|
self.logger.warning(f"knee got {val}, 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
|
@property
|
||||||
def mgain(self) -> float:
|
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
|
@mgain.setter
|
||||||
def mgain(self, val: float):
|
def mgain(self, val: float):
|
||||||
if not 0 <= val <= 24:
|
if not 0 <= val <= 24:
|
||||||
raise XAirRemoteError("expected value in range 0.0 to 24.0")
|
self.logger.warning(f"mgain got {val}, 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
|
@property
|
||||||
def attack(self) -> int:
|
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
|
@attack.setter
|
||||||
def attack(self, val: int):
|
def attack(self, val: int):
|
||||||
if not 0 <= val <= 120:
|
if not 0 <= val <= 120:
|
||||||
raise XAirRemoteError("expected value in range 0 to 120")
|
self.logger.warning(f"attack got {val}, 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
|
@property
|
||||||
def hold(self) -> Union[float, int]:
|
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)
|
return round(val, 1) if val < 100 else int(val)
|
||||||
|
|
||||||
@hold.setter
|
@hold.setter
|
||||||
def hold(self, val: float):
|
def hold(self, val: float):
|
||||||
if not 0.02 <= val <= 2000:
|
if not 0.02 <= val <= 2000:
|
||||||
raise XAirRemoteError("expected value in range 0.02 to 2000.0")
|
self.logger.warning(
|
||||||
self.setter("hold", log_set(0.02, 2000, val))
|
f"hold got {val}, expected value in range 0.02 to 2000.0"
|
||||||
|
)
|
||||||
|
self.setter("hold", util.log_set(0.02, 2000, val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def release(self) -> int:
|
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
|
@release.setter
|
||||||
def release(self, val: int):
|
def release(self, val: int):
|
||||||
if not 5 <= val <= 4000:
|
if not 5 <= val <= 4000:
|
||||||
raise XAirRemoteError("expected value in range 5 to 4000")
|
self.logger.warning(f"release got {val}, 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
|
@property
|
||||||
def mix(self) -> int:
|
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
|
@mix.setter
|
||||||
def mix(self, val: int):
|
def mix(self, val: int):
|
||||||
if not 0 <= val <= 100:
|
if not 0 <= val <= 100:
|
||||||
raise XAirRemoteError("expected value in range 0 to 100")
|
self.logger.warning(f"mix got {val}, 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
|
@property
|
||||||
def keysource(self):
|
def keysource(self):
|
||||||
@@ -376,14 +389,16 @@ class Dyn:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def filterfreq(self) -> Union[float, int]:
|
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)
|
return int(retval) if retval > 1000 else round(retval, 1)
|
||||||
|
|
||||||
@filterfreq.setter
|
@filterfreq.setter
|
||||||
def filterfreq(self, val: Union[float, int]):
|
def filterfreq(self, val: Union[float, int]):
|
||||||
if not 20 <= val <= 20000:
|
if not 20 <= val <= 20000:
|
||||||
raise XAirRemoteError("expected value in range 20 to 20000")
|
self.logger.warning(
|
||||||
self.setter("filter/f", log_set(20, 20000, val))
|
f"filterfreq got {val}, expected value in range 20 to 20000"
|
||||||
|
)
|
||||||
|
self.setter("filter/f", util.log_set(20, 20000, val))
|
||||||
|
|
||||||
|
|
||||||
class Insert:
|
class Insert:
|
||||||
@@ -462,15 +477,12 @@ class EQ:
|
|||||||
def mode(self, val: str):
|
def mode(self, val: str):
|
||||||
opts = ("peq", "geq", "teq")
|
opts = ("peq", "geq", "teq")
|
||||||
if val not in opts:
|
if val not in opts:
|
||||||
raise XAirRemoteError(f"expected one of {opts}")
|
self.logger.warning(f"mode got {val}, expected one of {opts}")
|
||||||
self.setter("mode", opts.index(val))
|
self.setter("mode", opts.index(val))
|
||||||
|
|
||||||
class EQBand:
|
class EQBand:
|
||||||
def __init__(self, i, remote, index):
|
def __init__(self, i, remote, index):
|
||||||
if index is None:
|
super(EQ.EQBand, self).__init__(remote, index)
|
||||||
super(EQ.EQBand, self).__init__(remote)
|
|
||||||
else:
|
|
||||||
super(EQ.EQBand, self).__init__(remote, index)
|
|
||||||
self.i = i
|
self.i = i
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -484,39 +496,45 @@ class EQ:
|
|||||||
|
|
||||||
@type.setter
|
@type.setter
|
||||||
def type(self, val: int):
|
def type(self, val: int):
|
||||||
self.setter(f"type", val)
|
self.setter("type", val)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def frequency(self) -> float:
|
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)
|
return round(retval, 1)
|
||||||
|
|
||||||
@frequency.setter
|
@frequency.setter
|
||||||
def frequency(self, val: float):
|
def frequency(self, val: float):
|
||||||
if not 20 <= val <= 20000:
|
if not 20 <= val <= 20000:
|
||||||
raise XAirRemoteError("expected value in range 20.0 to 20000.0")
|
self.logger.warning(
|
||||||
self.setter("f", log_set(20, 20000, val))
|
f"frequency got {val}, expected value in range 20.0 to 20000.0"
|
||||||
|
)
|
||||||
|
self.setter("f", util.log_set(20, 20000, val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def gain(self) -> float:
|
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
|
@gain.setter
|
||||||
def gain(self, val: float):
|
def gain(self, val: float):
|
||||||
if not -15 <= val <= 15:
|
if not -15 <= val <= 15:
|
||||||
raise XAirRemoteError("expected value in range -15.0 to 15.0")
|
self.logger.warning(
|
||||||
self.setter("g", lin_set(-15, 15, val))
|
f"gain got {val}, expected value in range -15.0 to 15.0"
|
||||||
|
)
|
||||||
|
self.setter("g", util.lin_set(-15, 15, val))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def quality(self) -> float:
|
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)
|
return round(retval, 1)
|
||||||
|
|
||||||
@quality.setter
|
@quality.setter
|
||||||
def quality(self, val: float):
|
def quality(self, val: float):
|
||||||
if not 0.3 <= val <= 10:
|
if not 0.3 <= val <= 10:
|
||||||
raise XAirRemoteError("expected value in range 0.3 to 10.0")
|
self.logger.warning(
|
||||||
self.setter("q", log_set(0.3, 10, val))
|
f"quality got {val}, expected value in range 0.3 to 10.0"
|
||||||
|
)
|
||||||
|
self.setter("q", util.log_set(0.3, 10, val))
|
||||||
|
|
||||||
|
|
||||||
class GEQ:
|
class GEQ:
|
||||||
@@ -531,7 +549,7 @@ class GEQ:
|
|||||||
f"slider_{param}": geq_prop(param)
|
f"slider_{param}": geq_prop(param)
|
||||||
for param in [
|
for param in [
|
||||||
"20", "25", "31_5", "40", "50", "63", "80", "100", "125",
|
"20", "25", "31_5", "40", "50", "63", "80", "100", "125",
|
||||||
"160", "200", "250", "315" "400", "500", "630", "800", "1k",
|
"160", "200", "250", "315", "400", "500", "630", "800", "1k",
|
||||||
"1k25", "1k6", "2k", "2k5", "3k15", "4k", "5k", "6k3", "8k",
|
"1k25", "1k6", "2k", "2k5", "3k15", "4k", "5k", "6k3", "8k",
|
||||||
"10k", "12k5", "16k", "20k",
|
"10k", "12k5", "16k", "20k",
|
||||||
]
|
]
|
||||||
@@ -561,13 +579,14 @@ class Mix:
|
|||||||
self.setter("on", 1 if val else 0)
|
self.setter("on", 1 if val else 0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@util.db_from
|
||||||
def fader(self) -> float:
|
def fader(self) -> float:
|
||||||
retval = self.getter("fader")[0]
|
return self.getter("fader")[0]
|
||||||
return _get_fader_val(retval)
|
|
||||||
|
|
||||||
@fader.setter
|
@fader.setter
|
||||||
|
@util.db_to
|
||||||
def fader(self, val: float):
|
def fader(self, val: float):
|
||||||
_set_fader_val(self, val)
|
self.setter("fader", val)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lr(self) -> bool:
|
def lr(self) -> bool:
|
||||||
@@ -617,10 +636,38 @@ class Automix:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def weight(self) -> float:
|
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
|
@weight.setter
|
||||||
def weight(self, val: float):
|
def weight(self, val: float):
|
||||||
if not -12 <= val <= 12:
|
if not -12 <= val <= 12:
|
||||||
raise XAirRemoteError("expected value in range -12.0 to 12.0")
|
self.logger.warning(
|
||||||
self.setter("weight", lin_set(-12, 12, val))
|
f"weight got {val}, expected value in range -12.0 to 12.0"
|
||||||
|
)
|
||||||
|
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) -> float:
|
||||||
|
return self.getter("level")[0]
|
||||||
|
|
||||||
|
@level.setter
|
||||||
|
@util.db_to
|
||||||
|
def level(self, val: float):
|
||||||
|
self.setter("level", val)
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import abc
|
import abc
|
||||||
|
import logging
|
||||||
|
|
||||||
from .errors import XAirRemoteError
|
|
||||||
from .meta import mute_prop
|
from .meta import mute_prop
|
||||||
from .shared import EQ, GEQ, Automix, Config, Dyn, Gate, Group, Insert, Mix, Preamp
|
from .shared import EQ, Automix, Config, Dyn, Gate, Group, Insert, Mix, Preamp, Send
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IStrip(abc.ABC):
|
class IStrip(abc.ABC):
|
||||||
@@ -11,6 +13,7 @@ class IStrip(abc.ABC):
|
|||||||
def __init__(self, remote, index: int):
|
def __init__(self, remote, index: int):
|
||||||
self._remote = remote
|
self._remote = remote
|
||||||
self.index = index + 1
|
self.index = index + 1
|
||||||
|
self.logger = logger.getChild(self.__class__.__name__)
|
||||||
|
|
||||||
def getter(self, param: str) -> tuple:
|
def getter(self, param: str) -> tuple:
|
||||||
return self._remote.query(f"{self.address}/{param}")
|
return self._remote.query(f"{self.address}/{param}")
|
||||||
@@ -56,6 +59,10 @@ class Strip(IStrip):
|
|||||||
Automix,
|
Automix,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
"send": tuple(
|
||||||
|
Send.make(cls, i, remote, index)
|
||||||
|
for i in range(remote.kind.num_bus + remote.kind.num_fx)
|
||||||
|
),
|
||||||
"mute": mute_prop(),
|
"mute": mute_prop(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import functools
|
||||||
from math import exp, log
|
from math import exp, log
|
||||||
|
|
||||||
|
|
||||||
@@ -17,61 +18,48 @@ def log_set(min, max, val):
|
|||||||
return log(val / min) / log(max / min)
|
return log(val / min) / log(max / min)
|
||||||
|
|
||||||
|
|
||||||
def _get_fader_val(retval):
|
def db_from(func):
|
||||||
if retval >= 1:
|
"""fader|level converter for getters"""
|
||||||
return 10
|
|
||||||
elif retval >= 0.5:
|
@functools.wraps(func)
|
||||||
return round((40 * retval) - 30, 1)
|
def wrapper(*args, **kwargs):
|
||||||
elif retval >= 0.25:
|
retval = func(*args, **kwargs)
|
||||||
return round((80 * retval) - 50, 1)
|
|
||||||
elif retval >= 0.0625:
|
if retval >= 1:
|
||||||
return round((160 * retval) - 70, 1)
|
return 10
|
||||||
elif retval >= 0:
|
elif retval >= 0.5:
|
||||||
return round((480 * retval) - 90, 1)
|
return round((40 * retval) - 30, 1)
|
||||||
else:
|
elif retval >= 0.25:
|
||||||
return -90
|
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
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def _set_fader_val(self, val):
|
def db_to(func):
|
||||||
if val >= 10:
|
"""fader|level converter for setters"""
|
||||||
self.setter("fader", 1)
|
|
||||||
elif val >= -10:
|
|
||||||
self.setter("fader", (val + 30) / 40)
|
|
||||||
elif val >= -30:
|
|
||||||
self.setter("fader", (val + 50) / 80)
|
|
||||||
elif val >= -60:
|
|
||||||
self.setter("fader", (val + 70) / 160)
|
|
||||||
elif val >= -90:
|
|
||||||
self.setter("fader", (val + 90) / 480)
|
|
||||||
else:
|
|
||||||
self.setter("fader", 0)
|
|
||||||
|
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
param, val = args
|
||||||
|
if val >= 10:
|
||||||
|
val = 1
|
||||||
|
elif val >= -10:
|
||||||
|
val = (val + 30) / 40
|
||||||
|
elif val >= -30:
|
||||||
|
val = (val + 50) / 80
|
||||||
|
elif val >= -60:
|
||||||
|
val = (val + 70) / 160
|
||||||
|
elif val >= -90:
|
||||||
|
val = (val + 90) / 480
|
||||||
|
else:
|
||||||
|
val = 0
|
||||||
|
|
||||||
def _get_level_val(retval):
|
func(param, val, **kwargs)
|
||||||
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
|
|
||||||
|
|
||||||
|
return wrapper
|
||||||
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)
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ from .lr import LR
|
|||||||
from .rtn import AuxRtn, FxRtn
|
from .rtn import AuxRtn, FxRtn
|
||||||
from .strip import Strip
|
from .strip import Strip
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class OSCClientServer(BlockingOSCUDPServer):
|
class OSCClientServer(BlockingOSCUDPServer):
|
||||||
def __init__(self, address: str, dispatcher: Dispatcher):
|
def __init__(self, address: str, dispatcher: Dispatcher):
|
||||||
@@ -45,8 +47,6 @@ class OSCClientServer(BlockingOSCUDPServer):
|
|||||||
class XAirRemote(abc.ABC):
|
class XAirRemote(abc.ABC):
|
||||||
"""Handles the communication with the mixer via the OSC protocol"""
|
"""Handles the communication with the mixer via the OSC protocol"""
|
||||||
|
|
||||||
logger = logging.getLogger("xair.xairremote")
|
|
||||||
|
|
||||||
_CONNECT_TIMEOUT = 0.5
|
_CONNECT_TIMEOUT = 0.5
|
||||||
|
|
||||||
_info_response = []
|
_info_response = []
|
||||||
@@ -57,6 +57,7 @@ class XAirRemote(abc.ABC):
|
|||||||
self.xair_ip = kwargs["ip"] or self._ip_from_toml()
|
self.xair_ip = kwargs["ip"] or self._ip_from_toml()
|
||||||
self.xair_port = kwargs["port"]
|
self.xair_port = kwargs["port"]
|
||||||
self._delay = kwargs["delay"]
|
self._delay = kwargs["delay"]
|
||||||
|
self.logger = logger.getChild(self.__class__.__name__)
|
||||||
if not self.xair_ip:
|
if not self.xair_ip:
|
||||||
raise XAirRemoteError("No valid ip detected")
|
raise XAirRemoteError("No valid ip detected")
|
||||||
self.server = OSCClientServer((self.xair_ip, self.xair_port), dispatcher)
|
self.server = OSCClientServer((self.xair_ip, self.xair_port), dispatcher)
|
||||||
@@ -80,7 +81,7 @@ class XAirRemote(abc.ABC):
|
|||||||
raise XAirRemoteError(
|
raise XAirRemoteError(
|
||||||
"Failed to setup OSC connection to mixer. Please check for correct ip address."
|
"Failed to setup OSC connection to mixer. Please check for correct ip address."
|
||||||
)
|
)
|
||||||
print(
|
self.logger.info(
|
||||||
f"Successfully connected to {self.info_response[2]} at {self.info_response[0]}."
|
f"Successfully connected to {self.info_response[2]} at {self.info_response[0]}."
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -174,9 +175,10 @@ def request_remote_obj(kind_id: str, *args, **kwargs) -> XAirRemote:
|
|||||||
|
|
||||||
Returns a reference to an XAirRemote class of a kind
|
Returns a reference to an XAirRemote class of a kind
|
||||||
"""
|
"""
|
||||||
|
|
||||||
XAIRREMOTE_cls = None
|
XAIRREMOTE_cls = None
|
||||||
try:
|
try:
|
||||||
XAIRREMOTE_cls = _remotes[kind_id]
|
XAIRREMOTE_cls = _remotes[kind_id]
|
||||||
except ValueError as e:
|
except KeyError as e:
|
||||||
raise SystemExit(e)
|
raise XAirRemoteError(f"Unknown mixer kind '{kind_id}'") from e
|
||||||
return XAIRREMOTE_cls(*args, **kwargs)
|
return XAIRREMOTE_cls(*args, **kwargs)
|
||||||
|
|||||||
Reference in New Issue
Block a user