sonance-py 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sonance_py-0.1.0/PKG-INFO +93 -0
- sonance_py-0.1.0/README.md +83 -0
- sonance_py-0.1.0/pyproject.toml +43 -0
- sonance_py-0.1.0/src/sonance_py/__init__.py +52 -0
- sonance_py-0.1.0/src/sonance_py/_wire_models.py +302 -0
- sonance_py-0.1.0/src/sonance_py/amplifier.py +716 -0
- sonance_py-0.1.0/src/sonance_py/cli.py +94 -0
- sonance_py-0.1.0/src/sonance_py/models.py +359 -0
- sonance_py-0.1.0/src/sonance_py/output_cli.py +338 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: sonance-py
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: An async Python library and CLI for interacting with Sonance DSP amplifiers.
|
|
5
|
+
Requires-Dist: aiohttp>=3.12.0
|
|
6
|
+
Requires-Dist: pydantic>=2.12.0
|
|
7
|
+
Requires-Dist: typer>=0.12.5
|
|
8
|
+
Requires-Python: >=3.14
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# Sonance Py
|
|
12
|
+
|
|
13
|
+
Sonance Py is an async Python library for controlling Sonance DSP amplifiers,
|
|
14
|
+
including the DSP8-130 and related models that expose the same unauthenticated
|
|
15
|
+
HTTP interface.
|
|
16
|
+
|
|
17
|
+
The project is intended to support a future Home Assistant integration and a
|
|
18
|
+
Typer-based CLI for local development, testing, and troubleshooting.
|
|
19
|
+
|
|
20
|
+
## Current Status
|
|
21
|
+
|
|
22
|
+
This project is in early development. The initial client implements the basic
|
|
23
|
+
HTTP API shape discovered from the amplifier web UI:
|
|
24
|
+
|
|
25
|
+
- General settings read/write operations
|
|
26
|
+
- Input/output settings read/write operations
|
|
27
|
+
- EQ preset read/write/action operations
|
|
28
|
+
- Shared async HTTP session support
|
|
29
|
+
|
|
30
|
+
The CLI is not implemented yet.
|
|
31
|
+
|
|
32
|
+
## HTTP API
|
|
33
|
+
|
|
34
|
+
The amplifier web UI calls an unauthenticated endpoint at:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
/Web/Handler.php
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The API uses query parameters for reads and writes, and returns JSON state
|
|
41
|
+
objects. The documented API shape is available in:
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
Docs/http-api.md
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Basic Usage
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import asyncio
|
|
51
|
+
|
|
52
|
+
from sonance_py import SonanceDSP
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
async def main() -> None:
|
|
56
|
+
async with SonanceDSP("192.168.1.50") as amp:
|
|
57
|
+
general = await amp.read_general()
|
|
58
|
+
print(general.amplifier_model)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
asyncio.run(main())
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Development
|
|
65
|
+
|
|
66
|
+
This project uses UV for dependency management and packaging.
|
|
67
|
+
|
|
68
|
+
Install dependencies:
|
|
69
|
+
|
|
70
|
+
```shell
|
|
71
|
+
uv sync
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Run Ruff:
|
|
75
|
+
|
|
76
|
+
```shell
|
|
77
|
+
uv run ruff check .
|
|
78
|
+
uv run ruff format . --check
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Build the package:
|
|
82
|
+
|
|
83
|
+
```shell
|
|
84
|
+
uv build
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Notes
|
|
88
|
+
|
|
89
|
+
- The device endpoint is unauthenticated HTTP.
|
|
90
|
+
- API indexes are zero-based because that is how the web UI addresses arrays.
|
|
91
|
+
- The project targets Python 3.14 and newer.
|
|
92
|
+
- Behavior still needs validation against real amplifier hardware and firmware
|
|
93
|
+
versions.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Sonance Py
|
|
2
|
+
|
|
3
|
+
Sonance Py is an async Python library for controlling Sonance DSP amplifiers,
|
|
4
|
+
including the DSP8-130 and related models that expose the same unauthenticated
|
|
5
|
+
HTTP interface.
|
|
6
|
+
|
|
7
|
+
The project is intended to support a future Home Assistant integration and a
|
|
8
|
+
Typer-based CLI for local development, testing, and troubleshooting.
|
|
9
|
+
|
|
10
|
+
## Current Status
|
|
11
|
+
|
|
12
|
+
This project is in early development. The initial client implements the basic
|
|
13
|
+
HTTP API shape discovered from the amplifier web UI:
|
|
14
|
+
|
|
15
|
+
- General settings read/write operations
|
|
16
|
+
- Input/output settings read/write operations
|
|
17
|
+
- EQ preset read/write/action operations
|
|
18
|
+
- Shared async HTTP session support
|
|
19
|
+
|
|
20
|
+
The CLI is not implemented yet.
|
|
21
|
+
|
|
22
|
+
## HTTP API
|
|
23
|
+
|
|
24
|
+
The amplifier web UI calls an unauthenticated endpoint at:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
/Web/Handler.php
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The API uses query parameters for reads and writes, and returns JSON state
|
|
31
|
+
objects. The documented API shape is available in:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
Docs/http-api.md
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Basic Usage
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import asyncio
|
|
41
|
+
|
|
42
|
+
from sonance_py import SonanceDSP
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
async def main() -> None:
|
|
46
|
+
async with SonanceDSP("192.168.1.50") as amp:
|
|
47
|
+
general = await amp.read_general()
|
|
48
|
+
print(general.amplifier_model)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
asyncio.run(main())
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Development
|
|
55
|
+
|
|
56
|
+
This project uses UV for dependency management and packaging.
|
|
57
|
+
|
|
58
|
+
Install dependencies:
|
|
59
|
+
|
|
60
|
+
```shell
|
|
61
|
+
uv sync
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Run Ruff:
|
|
65
|
+
|
|
66
|
+
```shell
|
|
67
|
+
uv run ruff check .
|
|
68
|
+
uv run ruff format . --check
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Build the package:
|
|
72
|
+
|
|
73
|
+
```shell
|
|
74
|
+
uv build
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Notes
|
|
78
|
+
|
|
79
|
+
- The device endpoint is unauthenticated HTTP.
|
|
80
|
+
- API indexes are zero-based because that is how the web UI addresses arrays.
|
|
81
|
+
- The project targets Python 3.14 and newer.
|
|
82
|
+
- Behavior still needs validation against real amplifier hardware and firmware
|
|
83
|
+
versions.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "sonance-py"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "An async Python library and CLI for interacting with Sonance DSP amplifiers."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.14"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"aiohttp>=3.12.0",
|
|
9
|
+
"pydantic>=2.12.0",
|
|
10
|
+
"typer>=0.12.5",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[project.scripts]
|
|
14
|
+
sonance = "sonance_py.cli:app"
|
|
15
|
+
|
|
16
|
+
[dependency-groups]
|
|
17
|
+
dev = [
|
|
18
|
+
"pyright>=1.1.400",
|
|
19
|
+
"ruff>=0.14.0",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[build-system]
|
|
23
|
+
requires = ["uv_build>=0.11.14,<0.12"]
|
|
24
|
+
build-backend = "uv_build"
|
|
25
|
+
|
|
26
|
+
[tool.ruff]
|
|
27
|
+
target-version = "py314"
|
|
28
|
+
line-length = 88
|
|
29
|
+
src = ["src"]
|
|
30
|
+
|
|
31
|
+
[tool.ruff.lint]
|
|
32
|
+
select = [
|
|
33
|
+
"E",
|
|
34
|
+
"F",
|
|
35
|
+
"I",
|
|
36
|
+
"UP",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
[tool.pyright]
|
|
41
|
+
include = ["src", "main.py"]
|
|
42
|
+
pythonVersion = "3.14"
|
|
43
|
+
typeCheckingMode = "standard"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Async client for Sonance DSP amplifiers."""
|
|
2
|
+
|
|
3
|
+
from .amplifier import SonanceDSP, SonanceOutput
|
|
4
|
+
from .models import (
|
|
5
|
+
AutoOnMethod,
|
|
6
|
+
BasicStatus,
|
|
7
|
+
BridgeModeItem,
|
|
8
|
+
CrossoverBand,
|
|
9
|
+
CrossoverFilterType,
|
|
10
|
+
CrossoverSettings,
|
|
11
|
+
DelaySettings,
|
|
12
|
+
EqSettings,
|
|
13
|
+
GeneralSettings,
|
|
14
|
+
InOutSettings,
|
|
15
|
+
Limiter,
|
|
16
|
+
OnOff,
|
|
17
|
+
Output,
|
|
18
|
+
OutputGroup,
|
|
19
|
+
OutputGroupItem,
|
|
20
|
+
ParametricEqBand,
|
|
21
|
+
PresetItem,
|
|
22
|
+
SourceMode,
|
|
23
|
+
StereoMode,
|
|
24
|
+
TiltBand,
|
|
25
|
+
TiltSettings,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"AutoOnMethod",
|
|
30
|
+
"BasicStatus",
|
|
31
|
+
"BridgeModeItem",
|
|
32
|
+
"CrossoverBand",
|
|
33
|
+
"CrossoverFilterType",
|
|
34
|
+
"CrossoverSettings",
|
|
35
|
+
"DelaySettings",
|
|
36
|
+
"EqSettings",
|
|
37
|
+
"GeneralSettings",
|
|
38
|
+
"InOutSettings",
|
|
39
|
+
"Limiter",
|
|
40
|
+
"OnOff",
|
|
41
|
+
"Output",
|
|
42
|
+
"OutputGroupItem",
|
|
43
|
+
"OutputGroup",
|
|
44
|
+
"ParametricEqBand",
|
|
45
|
+
"PresetItem",
|
|
46
|
+
"SonanceDSP",
|
|
47
|
+
"SonanceOutput",
|
|
48
|
+
"SourceMode",
|
|
49
|
+
"StereoMode",
|
|
50
|
+
"TiltBand",
|
|
51
|
+
"TiltSettings",
|
|
52
|
+
]
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"""Pydantic models for deserializing Sonance DSP HTTP API payloads."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
4
|
+
|
|
5
|
+
from .models import (
|
|
6
|
+
AutoOnMethod,
|
|
7
|
+
BasicStatus,
|
|
8
|
+
BridgeModeItem,
|
|
9
|
+
CrossoverBand,
|
|
10
|
+
CrossoverFilterType,
|
|
11
|
+
CrossoverSettings,
|
|
12
|
+
DelaySettings,
|
|
13
|
+
EqSettings,
|
|
14
|
+
GeneralSettings,
|
|
15
|
+
InOutSettings,
|
|
16
|
+
Limiter,
|
|
17
|
+
OnOff,
|
|
18
|
+
OutputGroup,
|
|
19
|
+
OutputGroupItem,
|
|
20
|
+
ParametricEqBand,
|
|
21
|
+
PresetItem,
|
|
22
|
+
SourceMode,
|
|
23
|
+
StereoMode,
|
|
24
|
+
TiltBand,
|
|
25
|
+
TiltSettings,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SonanceWireModel(BaseModel):
|
|
30
|
+
"""Base model for wire-format API payloads."""
|
|
31
|
+
|
|
32
|
+
model_config = ConfigDict(extra="allow", populate_by_name=True)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class WirePresetItem(SonanceWireModel):
|
|
36
|
+
"""Named preset option returned by the amplifier."""
|
|
37
|
+
|
|
38
|
+
name: str
|
|
39
|
+
value: str
|
|
40
|
+
|
|
41
|
+
def to_model(self) -> PresetItem:
|
|
42
|
+
"""Convert the wire payload to a public dataclass."""
|
|
43
|
+
|
|
44
|
+
return PresetItem(name=self.name, value=self.value)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class WireGeneralSettings(SonanceWireModel):
|
|
48
|
+
"""Payload returned by the general settings read endpoint."""
|
|
49
|
+
|
|
50
|
+
ip_address: str = Field(alias="ip-address")
|
|
51
|
+
ip_subnet_mask: str = Field(alias="ip-subnet-mask")
|
|
52
|
+
dhcp_switch: OnOff = Field(alias="dhcp-switch")
|
|
53
|
+
flash_power_switch: OnOff = Field(alias="flash-power-switch")
|
|
54
|
+
power: OnOff
|
|
55
|
+
standby_mode: OnOff = Field(alias="standby-mode")
|
|
56
|
+
auto_on_method: AutoOnMethod = Field(alias="auto-on-method")
|
|
57
|
+
auto_on_delay: str = Field(alias="auto-on-delay")
|
|
58
|
+
amplifier_name: str = Field(alias="amplifier-name")
|
|
59
|
+
dealer_name: str = Field(alias="dealer-name")
|
|
60
|
+
amplifier_model: str = Field(alias="amplifier-model")
|
|
61
|
+
installer_name: str = Field(alias="installer-name")
|
|
62
|
+
customer_name: str = Field(alias="customer-name")
|
|
63
|
+
installition_date: str = Field(alias="installition-date")
|
|
64
|
+
firmware_version: str = Field(alias="firmware-version")
|
|
65
|
+
serial_number: str = Field(alias="serial-number")
|
|
66
|
+
|
|
67
|
+
def to_basic_status(self) -> BasicStatus:
|
|
68
|
+
"""Convert the wire payload to a compact public status dataclass."""
|
|
69
|
+
|
|
70
|
+
return BasicStatus(
|
|
71
|
+
power=self.power,
|
|
72
|
+
firmware_version=self.firmware_version,
|
|
73
|
+
amplifier_name=self.amplifier_name,
|
|
74
|
+
serial_number=self.serial_number,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def to_model(self) -> GeneralSettings:
|
|
78
|
+
"""Convert the wire payload to a public dataclass."""
|
|
79
|
+
|
|
80
|
+
return GeneralSettings(
|
|
81
|
+
ip_address=self.ip_address,
|
|
82
|
+
ip_subnet_mask=self.ip_subnet_mask,
|
|
83
|
+
dhcp_switch=self.dhcp_switch,
|
|
84
|
+
flash_power_switch=self.flash_power_switch,
|
|
85
|
+
power=self.power,
|
|
86
|
+
standby_mode=self.standby_mode,
|
|
87
|
+
auto_on_method=self.auto_on_method,
|
|
88
|
+
auto_on_delay=self.auto_on_delay,
|
|
89
|
+
amplifier_name=self.amplifier_name,
|
|
90
|
+
dealer_name=self.dealer_name,
|
|
91
|
+
amplifier_model=self.amplifier_model,
|
|
92
|
+
installer_name=self.installer_name,
|
|
93
|
+
customer_name=self.customer_name,
|
|
94
|
+
installition_date=self.installition_date,
|
|
95
|
+
firmware_version=self.firmware_version,
|
|
96
|
+
serial_number=self.serial_number,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class WireOutputGroupItem(SonanceWireModel):
|
|
101
|
+
"""Output group option returned by the input/output settings endpoint."""
|
|
102
|
+
|
|
103
|
+
name: str
|
|
104
|
+
value: OutputGroup
|
|
105
|
+
|
|
106
|
+
def to_model(self) -> OutputGroupItem:
|
|
107
|
+
"""Convert the wire payload to a public dataclass."""
|
|
108
|
+
|
|
109
|
+
return OutputGroupItem(name=self.name, value=self.value)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class WireBridgeModeItem(SonanceWireModel):
|
|
113
|
+
"""Bridge mode option returned by the input/output settings endpoint."""
|
|
114
|
+
|
|
115
|
+
name: str
|
|
116
|
+
value: OnOff
|
|
117
|
+
|
|
118
|
+
def to_model(self) -> BridgeModeItem:
|
|
119
|
+
"""Convert the wire payload to a public dataclass."""
|
|
120
|
+
|
|
121
|
+
return BridgeModeItem(name=self.name, value=self.value)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class WireInOutSettings(SonanceWireModel):
|
|
125
|
+
"""Payload returned by the input/output settings read endpoint."""
|
|
126
|
+
|
|
127
|
+
dsp_preset_items: list[WirePresetItem] = Field(alias="dsp-preset-items")
|
|
128
|
+
input_names: list[str] = Field(alias="input-names")
|
|
129
|
+
input_titles: list[str] = Field(alias="input-titles")
|
|
130
|
+
output_titles: list[str] = Field(alias="output-titles")
|
|
131
|
+
level_trim_dbs: list[str] = Field(alias="level-trim-dBs")
|
|
132
|
+
output_names: list[str] = Field(alias="output-names")
|
|
133
|
+
stereo_or_mono: list[StereoMode] = Field(alias="stereo-or-mono")
|
|
134
|
+
dsp_presets: list[int] = Field(alias="dsp-presets")
|
|
135
|
+
output_group_items: list[WireOutputGroupItem] = Field(alias="output-group-items")
|
|
136
|
+
output_groups: list[OutputGroup] = Field(alias="output-groups")
|
|
137
|
+
bridge_mode_items: list[WireBridgeModeItem] = Field(alias="bridge-mode-items")
|
|
138
|
+
bridge_modes: list[OnOff] = Field(alias="bridge-modes")
|
|
139
|
+
sources_1: list[int] = Field(alias="sources-1")
|
|
140
|
+
sources_2: list[int] = Field(alias="sources-2")
|
|
141
|
+
mode_sources: list[SourceMode] = Field(alias="mode-sources")
|
|
142
|
+
output_volumes: list[str] = Field(alias="output-volumes")
|
|
143
|
+
turn_on_volumes: list[str] = Field(alias="turn-on-volumes")
|
|
144
|
+
maximum_volumes: list[str] = Field(alias="maximum-volumes")
|
|
145
|
+
gain_offset: list[str] = Field(alias="gain-offset")
|
|
146
|
+
mute_volumes: list[OnOff] = Field(alias="mute-volumes")
|
|
147
|
+
|
|
148
|
+
def to_model(self) -> InOutSettings:
|
|
149
|
+
"""Convert the wire payload to a public dataclass."""
|
|
150
|
+
|
|
151
|
+
return InOutSettings(
|
|
152
|
+
dsp_preset_items=[item.to_model() for item in self.dsp_preset_items],
|
|
153
|
+
input_names=self.input_names,
|
|
154
|
+
input_titles=self.input_titles,
|
|
155
|
+
output_titles=self.output_titles,
|
|
156
|
+
level_trim_dbs=self.level_trim_dbs,
|
|
157
|
+
output_names=self.output_names,
|
|
158
|
+
stereo_or_mono=self.stereo_or_mono,
|
|
159
|
+
dsp_presets=self.dsp_presets,
|
|
160
|
+
output_group_items=[item.to_model() for item in self.output_group_items],
|
|
161
|
+
output_groups=self.output_groups,
|
|
162
|
+
bridge_mode_items=[item.to_model() for item in self.bridge_mode_items],
|
|
163
|
+
bridge_modes=self.bridge_modes,
|
|
164
|
+
sources_1=self.sources_1,
|
|
165
|
+
sources_2=self.sources_2,
|
|
166
|
+
mode_sources=self.mode_sources,
|
|
167
|
+
output_volumes=self.output_volumes,
|
|
168
|
+
turn_on_volumes=self.turn_on_volumes,
|
|
169
|
+
maximum_volumes=self.maximum_volumes,
|
|
170
|
+
gain_offset=self.gain_offset,
|
|
171
|
+
mute_volumes=self.mute_volumes,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class WireParametricEqBand(SonanceWireModel):
|
|
176
|
+
"""Single parametric EQ band."""
|
|
177
|
+
|
|
178
|
+
enable_status: OnOff = Field(alias="enable-status")
|
|
179
|
+
freq: int
|
|
180
|
+
q: float
|
|
181
|
+
gain: float
|
|
182
|
+
|
|
183
|
+
def to_model(self) -> ParametricEqBand:
|
|
184
|
+
"""Convert the wire payload to a public dataclass."""
|
|
185
|
+
|
|
186
|
+
return ParametricEqBand(
|
|
187
|
+
enable_status=self.enable_status,
|
|
188
|
+
freq=self.freq,
|
|
189
|
+
q=self.q,
|
|
190
|
+
gain=self.gain,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class WireTiltBand(SonanceWireModel):
|
|
195
|
+
"""Low or high tilt EQ band."""
|
|
196
|
+
|
|
197
|
+
on_or_off: OnOff = Field(alias="on-or-off")
|
|
198
|
+
freq: int
|
|
199
|
+
gain: float
|
|
200
|
+
|
|
201
|
+
def to_model(self) -> TiltBand:
|
|
202
|
+
"""Convert the wire payload to a public dataclass."""
|
|
203
|
+
|
|
204
|
+
return TiltBand(on_or_off=self.on_or_off, freq=self.freq, gain=self.gain)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class WireTiltSettings(SonanceWireModel):
|
|
208
|
+
"""Tilt control settings."""
|
|
209
|
+
|
|
210
|
+
low: WireTiltBand
|
|
211
|
+
high: WireTiltBand
|
|
212
|
+
|
|
213
|
+
def to_model(self) -> TiltSettings:
|
|
214
|
+
"""Convert the wire payload to a public dataclass."""
|
|
215
|
+
|
|
216
|
+
return TiltSettings(low=self.low.to_model(), high=self.high.to_model())
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class WireCrossoverBand(SonanceWireModel):
|
|
220
|
+
"""Low-pass or high-pass crossover settings."""
|
|
221
|
+
|
|
222
|
+
on_or_off: OnOff = Field(alias="on-or-off")
|
|
223
|
+
freq: int
|
|
224
|
+
filter_type: CrossoverFilterType = Field(alias="filter-type")
|
|
225
|
+
|
|
226
|
+
def to_model(self) -> CrossoverBand:
|
|
227
|
+
"""Convert the wire payload to a public dataclass."""
|
|
228
|
+
|
|
229
|
+
return CrossoverBand(
|
|
230
|
+
on_or_off=self.on_or_off,
|
|
231
|
+
freq=self.freq,
|
|
232
|
+
filter_type=self.filter_type,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
class WireCrossoverSettings(SonanceWireModel):
|
|
237
|
+
"""Crossover settings."""
|
|
238
|
+
|
|
239
|
+
low_pass: WireCrossoverBand = Field(alias="low-pass")
|
|
240
|
+
high_pass: WireCrossoverBand = Field(alias="high-pass")
|
|
241
|
+
|
|
242
|
+
def to_model(self) -> CrossoverSettings:
|
|
243
|
+
"""Convert the wire payload to a public dataclass."""
|
|
244
|
+
|
|
245
|
+
return CrossoverSettings(
|
|
246
|
+
low_pass=self.low_pass.to_model(),
|
|
247
|
+
high_pass=self.high_pass.to_model(),
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class WireDelaySettings(SonanceWireModel):
|
|
252
|
+
"""Delay settings in the units returned by the amplifier."""
|
|
253
|
+
|
|
254
|
+
seconds: float
|
|
255
|
+
feet: float
|
|
256
|
+
meters: float
|
|
257
|
+
|
|
258
|
+
def to_model(self) -> DelaySettings:
|
|
259
|
+
"""Convert the wire payload to a public dataclass."""
|
|
260
|
+
|
|
261
|
+
return DelaySettings(seconds=self.seconds, feet=self.feet, meters=self.meters)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
class WireEqSettings(SonanceWireModel):
|
|
265
|
+
"""Payload returned by the EQ settings read endpoint."""
|
|
266
|
+
|
|
267
|
+
output_names: list[str] = Field(alias="output-names")
|
|
268
|
+
dsp_presets: list[int] = Field(alias="dsp-presets")
|
|
269
|
+
output_titles: list[str] = Field(alias="output-titles")
|
|
270
|
+
amplifier_model: str = Field(alias="amplifier-model")
|
|
271
|
+
input_names: list[str] = Field(alias="input-names")
|
|
272
|
+
source_select: list[int] = Field(alias="source-select")
|
|
273
|
+
output_volumes: list[str] = Field(alias="output-volumes")
|
|
274
|
+
mute_volumes: list[OnOff] = Field(alias="mute-volumes")
|
|
275
|
+
eq_presets: list[WirePresetItem] = Field(alias="eq-presets")
|
|
276
|
+
current_eq_preset: str = Field(alias="current-eq-preset")
|
|
277
|
+
parametric_eq: list[WireParametricEqBand] = Field(alias="parametric-eq")
|
|
278
|
+
tilt: WireTiltSettings
|
|
279
|
+
crossover: WireCrossoverSettings
|
|
280
|
+
limiter_limiters: Limiter = Field(alias="limiter-limiters")
|
|
281
|
+
delay: WireDelaySettings
|
|
282
|
+
|
|
283
|
+
def to_model(self) -> EqSettings:
|
|
284
|
+
"""Convert the wire payload to a public dataclass."""
|
|
285
|
+
|
|
286
|
+
return EqSettings(
|
|
287
|
+
output_names=self.output_names,
|
|
288
|
+
dsp_presets=self.dsp_presets,
|
|
289
|
+
output_titles=self.output_titles,
|
|
290
|
+
amplifier_model=self.amplifier_model,
|
|
291
|
+
input_names=self.input_names,
|
|
292
|
+
source_select=self.source_select,
|
|
293
|
+
output_volumes=self.output_volumes,
|
|
294
|
+
mute_volumes=self.mute_volumes,
|
|
295
|
+
eq_presets=[item.to_model() for item in self.eq_presets],
|
|
296
|
+
current_eq_preset=self.current_eq_preset,
|
|
297
|
+
parametric_eq=[band.to_model() for band in self.parametric_eq],
|
|
298
|
+
tilt=self.tilt.to_model(),
|
|
299
|
+
crossover=self.crossover.to_model(),
|
|
300
|
+
limiter_limiters=self.limiter_limiters,
|
|
301
|
+
delay=self.delay.to_model(),
|
|
302
|
+
)
|