python-linkplay 0.1.0__tar.gz → 0.2.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.
- {python_linkplay-0.1.0/src/python_linkplay.egg-info → python_linkplay-0.2.0}/PKG-INFO +7 -3
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/README.md +4 -1
- python_linkplay-0.2.0/src/linkplay/__version__.py +1 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/linkplay/bridge.py +117 -13
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/linkplay/consts.py +30 -5
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/linkplay/controller.py +17 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/linkplay/endpoint.py +6 -1
- python_linkplay-0.2.0/src/linkplay/manufacturers.py +74 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0/src/python_linkplay.egg-info}/PKG-INFO +7 -3
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/python_linkplay.egg-info/SOURCES.txt +1 -0
- python_linkplay-0.1.0/src/linkplay/__version__.py +0 -1
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/LICENSE +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/pyproject.toml +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/setup.cfg +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/setup.py +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/linkplay/__init__.py +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/linkplay/__main__.py +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/linkplay/discovery.py +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/linkplay/exceptions.py +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/linkplay/utils.py +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/python_linkplay.egg-info/dependency_links.txt +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/python_linkplay.egg-info/not-zip-safe +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/python_linkplay.egg-info/requires.txt +0 -0
- {python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/python_linkplay.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: python_linkplay
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.2.0
|
4
4
|
Summary: A Python Library for Seamless LinkPlay Device Control
|
5
5
|
Author: Velleman Group nv
|
6
6
|
License: MIT
|
@@ -24,12 +24,13 @@ Requires-Dist: ruff>=0.5.4; extra == "testing"
|
|
24
24
|
Requires-Dist: tox>=4.6.0; extra == "testing"
|
25
25
|
Requires-Dist: typing-extensions>=4.6.3; extra == "testing"
|
26
26
|
Requires-Dist: pre-commit>=3.8.0; extra == "testing"
|
27
|
-
|
27
|
+
Dynamic: license-file
|
28
28
|
|
29
29
|
[](https://pypi.org/project/python-linkplay/)
|
30
30
|
[](https://github.com/velleman/python-linkplay/actions/workflows/release.yaml)
|
31
31
|
|
32
32
|
# python-linkplay
|
33
|
+
|
33
34
|
A Python Library for Seamless LinkPlay Device Control
|
34
35
|
|
35
36
|
## Intro
|
@@ -54,6 +55,9 @@ Welcome to python-linkplay, a powerful and user-friendly Python library designed
|
|
54
55
|
- https://developer.arylic.com/httpapi/
|
55
56
|
- http://airscope-audio.net/core2/pdf/airscope-module-http.pdf
|
56
57
|
- https://www.wiimhome.com/pdf/HTTP%20API%20for%20WiiM%20Mini.pdf
|
58
|
+
- https://www.wiimhome.com/pdf/HTTP%20API%20for%20WiiM%20Products.pdf
|
59
|
+
- https://github.com/DanBrezeanu/wiim-extended-http-api
|
60
|
+
- https://github.com/cvdlinden/wiim-httpapi
|
57
61
|
|
58
62
|
## Multiroom
|
59
63
|
|
@@ -1,8 +1,8 @@
|
|
1
|
-
|
2
1
|
[](https://pypi.org/project/python-linkplay/)
|
3
2
|
[](https://github.com/velleman/python-linkplay/actions/workflows/release.yaml)
|
4
3
|
|
5
4
|
# python-linkplay
|
5
|
+
|
6
6
|
A Python Library for Seamless LinkPlay Device Control
|
7
7
|
|
8
8
|
## Intro
|
@@ -27,6 +27,9 @@ Welcome to python-linkplay, a powerful and user-friendly Python library designed
|
|
27
27
|
- https://developer.arylic.com/httpapi/
|
28
28
|
- http://airscope-audio.net/core2/pdf/airscope-module-http.pdf
|
29
29
|
- https://www.wiimhome.com/pdf/HTTP%20API%20for%20WiiM%20Mini.pdf
|
30
|
+
- https://www.wiimhome.com/pdf/HTTP%20API%20for%20WiiM%20Products.pdf
|
31
|
+
- https://github.com/DanBrezeanu/wiim-extended-http-api
|
32
|
+
- https://github.com/cvdlinden/wiim-httpapi
|
30
33
|
|
31
34
|
## Multiroom
|
32
35
|
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = '0.2.0'
|
@@ -22,6 +22,7 @@ from linkplay.consts import (
|
|
22
22
|
)
|
23
23
|
from linkplay.endpoint import LinkPlayEndpoint
|
24
24
|
from linkplay.exceptions import LinkPlayInvalidDataException
|
25
|
+
from linkplay.manufacturers import MANUFACTURER_WIIM, get_info_from_project
|
25
26
|
from linkplay.utils import fixup_player_properties
|
26
27
|
|
27
28
|
|
@@ -57,6 +58,22 @@ class LinkPlayDevice:
|
|
57
58
|
"""The name of the device."""
|
58
59
|
return self.properties.get(DeviceAttribute.DEVICE_NAME, "")
|
59
60
|
|
61
|
+
@property
|
62
|
+
def manufacturer(self) -> str:
|
63
|
+
"""The manufacturer of the device."""
|
64
|
+
manufacturer, _ = get_info_from_project(
|
65
|
+
self.properties.get(DeviceAttribute.PROJECT, "")
|
66
|
+
)
|
67
|
+
return manufacturer
|
68
|
+
|
69
|
+
@property
|
70
|
+
def model(self) -> str:
|
71
|
+
"""The model of the device."""
|
72
|
+
_, model = get_info_from_project(
|
73
|
+
self.properties.get(DeviceAttribute.PROJECT, "")
|
74
|
+
)
|
75
|
+
return model
|
76
|
+
|
60
77
|
@property
|
61
78
|
def playmode_support(self) -> list[PlayingMode]:
|
62
79
|
"""Returns the player playmode support."""
|
@@ -69,21 +86,25 @@ class LinkPlayDevice:
|
|
69
86
|
playing_modes.insert(0, PlayingMode.NETWORK) # always supported
|
70
87
|
return playing_modes
|
71
88
|
|
89
|
+
@property
|
90
|
+
def mac(self) -> str | None:
|
91
|
+
"""Returns the mac address."""
|
92
|
+
mac = self.properties.get(DeviceAttribute.ETH_MAC_ADDRESS)
|
93
|
+
if mac == "00:00:00:00:00:00" or mac is None:
|
94
|
+
mac = self.properties.get(DeviceAttribute.STA_MAC_ADDRESS)
|
95
|
+
if mac == "00:00:00:00:00:00" or mac is None:
|
96
|
+
mac = self.properties.get(DeviceAttribute.MAC_ADDRESS)
|
97
|
+
return mac
|
98
|
+
|
72
99
|
@property
|
73
100
|
def eth(self) -> str | None:
|
74
101
|
"""Returns the ethernet address."""
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
return
|
81
|
-
eth2
|
82
|
-
if eth2
|
83
|
-
else eth0
|
84
|
-
if eth0
|
85
|
-
else self.properties.get(DeviceAttribute.APCLI0)
|
86
|
-
)
|
102
|
+
eth = self.properties.get(DeviceAttribute.ETH2)
|
103
|
+
if eth == "0.0.0.0" or eth == "" or eth is None:
|
104
|
+
eth = self.properties.get(DeviceAttribute.ETH0)
|
105
|
+
if eth == "0.0.0.0" or eth == "" or eth is None:
|
106
|
+
eth = self.properties.get(DeviceAttribute.APCLI0)
|
107
|
+
return eth
|
87
108
|
|
88
109
|
async def timesync(self) -> None:
|
89
110
|
"""Sync the time."""
|
@@ -166,7 +187,47 @@ class LinkPlayPlayer:
|
|
166
187
|
|
167
188
|
async def set_equalizer_mode(self, mode: EqualizerMode) -> None:
|
168
189
|
"""Set the equalizer mode."""
|
169
|
-
|
190
|
+
if self.bridge.device.manufacturer == MANUFACTURER_WIIM:
|
191
|
+
# WiiM devices have a different equalizer mode handling
|
192
|
+
# and don't support the general equalizer mode command
|
193
|
+
if mode not in self.available_equalizer_modes:
|
194
|
+
raise ValueError(
|
195
|
+
f"Invalid equalizer mode {mode}. Allowed equalizer modes are {self.available_equalizer_modes}."
|
196
|
+
)
|
197
|
+
|
198
|
+
if mode == EqualizerMode.NONE:
|
199
|
+
await self.bridge.json_request(LinkPlayCommand.WIIM_EQUALIZER_OFF)
|
200
|
+
else:
|
201
|
+
await self.bridge.json_request(
|
202
|
+
LinkPlayCommand.WIIM_EQ_LOAD.format(mode)
|
203
|
+
)
|
204
|
+
# WiiM doesn't update the property after setting it
|
205
|
+
self.properties[PlayerAttribute.EQUALIZER_MODE] = mode
|
206
|
+
else:
|
207
|
+
await self._set_normal_equalizer_mode(mode)
|
208
|
+
|
209
|
+
async def _set_normal_equalizer_mode(self, mode: EqualizerMode) -> None:
|
210
|
+
"""Set the equalizer mode."""
|
211
|
+
equalizer_mode_as_number = None
|
212
|
+
match mode:
|
213
|
+
case EqualizerMode.NONE:
|
214
|
+
equalizer_mode_as_number = "0"
|
215
|
+
case EqualizerMode.CLASSIC:
|
216
|
+
equalizer_mode_as_number = "1"
|
217
|
+
case EqualizerMode.POP:
|
218
|
+
equalizer_mode_as_number = "2"
|
219
|
+
case EqualizerMode.JAZZ:
|
220
|
+
equalizer_mode_as_number = "3"
|
221
|
+
case EqualizerMode.VOCAL:
|
222
|
+
equalizer_mode_as_number = "4"
|
223
|
+
if equalizer_mode_as_number is None:
|
224
|
+
raise ValueError(
|
225
|
+
f"Invalid equalizer mode {mode}. Allowed equalizer modes are {self.available_equalizer_modes}."
|
226
|
+
)
|
227
|
+
|
228
|
+
await self.bridge.request(
|
229
|
+
LinkPlayCommand.EQUALIZER_MODE.format(equalizer_mode_as_number)
|
230
|
+
)
|
170
231
|
|
171
232
|
async def set_loop_mode(self, mode: LoopMode) -> None:
|
172
233
|
"""Set the loop mode."""
|
@@ -256,10 +317,53 @@ class LinkPlayPlayer:
|
|
256
317
|
@property
|
257
318
|
def equalizer_mode(self) -> EqualizerMode:
|
258
319
|
"""Returns the current equalizer mode."""
|
320
|
+
if self.bridge.device.manufacturer == MANUFACTURER_WIIM:
|
321
|
+
return EqualizerMode(
|
322
|
+
self.properties.get(PlayerAttribute.EQUALIZER_MODE, EqualizerMode.NONE)
|
323
|
+
)
|
324
|
+
|
259
325
|
return EqualizerMode(
|
260
326
|
self.properties.get(PlayerAttribute.EQUALIZER_MODE, EqualizerMode.CLASSIC)
|
261
327
|
)
|
262
328
|
|
329
|
+
@property
|
330
|
+
def available_equalizer_modes(self) -> list[EqualizerMode]:
|
331
|
+
"""Returns the available equalizer modes."""
|
332
|
+
if self.bridge.device.manufacturer == MANUFACTURER_WIIM:
|
333
|
+
return [
|
334
|
+
EqualizerMode.NONE,
|
335
|
+
EqualizerMode.FLAT,
|
336
|
+
EqualizerMode.ACOUSTIC,
|
337
|
+
EqualizerMode.BASS_BOOSTER,
|
338
|
+
EqualizerMode.BASS_REDUCER,
|
339
|
+
EqualizerMode.CLASSICAL,
|
340
|
+
EqualizerMode.DANCE,
|
341
|
+
EqualizerMode.DEEP,
|
342
|
+
EqualizerMode.ELECTRONIC,
|
343
|
+
EqualizerMode.HIP_HOP,
|
344
|
+
EqualizerMode.JAZZ,
|
345
|
+
EqualizerMode.LATIN,
|
346
|
+
EqualizerMode.LOUDNESS,
|
347
|
+
EqualizerMode.LOUNGE,
|
348
|
+
EqualizerMode.PIANO,
|
349
|
+
EqualizerMode.POP,
|
350
|
+
EqualizerMode.R_B,
|
351
|
+
EqualizerMode.ROCK,
|
352
|
+
EqualizerMode.SMALL_SPEAKERS,
|
353
|
+
EqualizerMode.SPOKEN_WORD,
|
354
|
+
EqualizerMode.TREBLE_BOOSTER,
|
355
|
+
EqualizerMode.TREBLE_REDUCER,
|
356
|
+
EqualizerMode.VOCAL_BOOSTER,
|
357
|
+
]
|
358
|
+
|
359
|
+
return [
|
360
|
+
EqualizerMode.NONE,
|
361
|
+
EqualizerMode.CLASSIC,
|
362
|
+
EqualizerMode.POP,
|
363
|
+
EqualizerMode.JAZZ,
|
364
|
+
EqualizerMode.VOCAL,
|
365
|
+
]
|
366
|
+
|
263
367
|
@property
|
264
368
|
def speaker_type(self) -> SpeakerType:
|
265
369
|
"""Returns the current speaker the player is playing on."""
|
@@ -85,6 +85,8 @@ class LinkPlayCommand(StrEnum):
|
|
85
85
|
STOP = "setPlayerCmd:stop"
|
86
86
|
TOGGLE = "setPlayerCmd:onepause"
|
87
87
|
EQUALIZER_MODE = "setPlayerCmd:equalizer:{}"
|
88
|
+
WIIM_EQUALIZER_ON = "EQOn"
|
89
|
+
WIIM_EQUALIZER_OFF = "EQOff"
|
88
90
|
LOOP_MODE = "setPlayerCmd:loopmode:{}"
|
89
91
|
SWITCH_MODE = "setPlayerCmd:switchmode:{}"
|
90
92
|
M3U_PLAYLIST = "setPlayerCmd:m3u:play:{}"
|
@@ -97,6 +99,7 @@ class LinkPlayCommand(StrEnum):
|
|
97
99
|
MULTIROOM_JOIN = "ConnectMasterAp:JoinGroupMaster:eth{}:wifi0.0.0.0"
|
98
100
|
PLAY_PRESET = "MCUKeyShortClick:{}"
|
99
101
|
TIMESYNC = "timeSync:{}"
|
102
|
+
WIIM_EQ_LOAD = "EQLoad:{}"
|
100
103
|
|
101
104
|
|
102
105
|
class LinkPlayTcpUartCommand(StrEnum):
|
@@ -219,11 +222,33 @@ class LoopMode(StrEnum):
|
|
219
222
|
class EqualizerMode(StrEnum):
|
220
223
|
"""Defines the equalizer mode."""
|
221
224
|
|
222
|
-
NONE = "
|
223
|
-
CLASSIC = "
|
224
|
-
POP = "
|
225
|
-
JAZZ = "
|
226
|
-
VOCAL = "
|
225
|
+
NONE = "None"
|
226
|
+
CLASSIC = "Classic"
|
227
|
+
POP = "Pop"
|
228
|
+
JAZZ = "Jazz"
|
229
|
+
VOCAL = "Vocal"
|
230
|
+
|
231
|
+
# Custom equalizer modes specificly for WiiM devices
|
232
|
+
FLAT = "Flat"
|
233
|
+
ACOUSTIC = "Acoustic"
|
234
|
+
BASS_BOOSTER = "Bass Booster"
|
235
|
+
BASS_REDUCER = "Bass Reducer"
|
236
|
+
CLASSICAL = "Classical"
|
237
|
+
DANCE = "Dance"
|
238
|
+
DEEP = "Deep"
|
239
|
+
ELECTRONIC = "Electronic"
|
240
|
+
HIP_HOP = "Hip-Hop"
|
241
|
+
LATIN = "Latin"
|
242
|
+
LOUDNESS = "Loudness"
|
243
|
+
LOUNGE = "Lounge"
|
244
|
+
PIANO = "Piano"
|
245
|
+
R_B = "R&B"
|
246
|
+
ROCK = "Rock"
|
247
|
+
SMALL_SPEAKERS = "Small Speakers"
|
248
|
+
SPOKEN_WORD = "Spoken Word"
|
249
|
+
TREBLE_BOOSTER = "Treble Booster"
|
250
|
+
TREBLE_REDUCER = "Treble Reducer"
|
251
|
+
VOCAL_BOOSTER = "Vocal Booster"
|
227
252
|
|
228
253
|
|
229
254
|
class PlayingStatus(StrEnum):
|
@@ -31,6 +31,15 @@ class LinkPlayController:
|
|
31
31
|
]
|
32
32
|
self.bridges.extend(new_bridges)
|
33
33
|
|
34
|
+
async def find_bridge(self, bridge_uuid: str) -> LinkPlayBridge | None:
|
35
|
+
"""Find a LinkPlay device by its bridge uuid."""
|
36
|
+
|
37
|
+
for bridge in self.bridges:
|
38
|
+
if bridge.device.uuid == bridge_uuid:
|
39
|
+
return bridge
|
40
|
+
|
41
|
+
return None
|
42
|
+
|
34
43
|
async def add_bridge(self, bridge_to_add: LinkPlayBridge) -> None:
|
35
44
|
"""Add given LinkPlay device if not already added."""
|
36
45
|
|
@@ -39,6 +48,14 @@ class LinkPlayController:
|
|
39
48
|
if bridge_to_add.device.uuid not in current_bridges:
|
40
49
|
self.bridges.append(bridge_to_add)
|
41
50
|
|
51
|
+
async def remove_bridge(self, bridge_to_remove: LinkPlayBridge) -> None:
|
52
|
+
"""Remove given LinkPlay device if not already deleted."""
|
53
|
+
|
54
|
+
# Remove bridge
|
55
|
+
current_bridges = [bridge.device.uuid for bridge in self.bridges]
|
56
|
+
if bridge_to_remove.device.uuid in current_bridges:
|
57
|
+
self.bridges.remove(bridge_to_remove)
|
58
|
+
|
42
59
|
async def discover_multirooms(self) -> None:
|
43
60
|
"""Attempts to discover multirooms on the local network."""
|
44
61
|
|
@@ -37,7 +37,12 @@ class LinkPlayApiEndpoint(LinkPlayEndpoint):
|
|
37
37
|
"http",
|
38
38
|
"https",
|
39
39
|
], "Protocol must be either 'http' or 'https'"
|
40
|
-
|
40
|
+
include_port = (protocol == "http" and port != 80) or (
|
41
|
+
protocol == "https" and port != 443
|
42
|
+
)
|
43
|
+
port_suffix = f":{port}" if include_port else ""
|
44
|
+
self._endpoint: str = f"{protocol}://{endpoint}{port_suffix}"
|
45
|
+
|
41
46
|
self._session: ClientSession = session
|
42
47
|
|
43
48
|
def to_dict(self):
|
@@ -0,0 +1,74 @@
|
|
1
|
+
"""Manufacturers and their devices for the LinkPlay component."""
|
2
|
+
|
3
|
+
from typing import Final
|
4
|
+
|
5
|
+
MANUFACTURER_ARTSOUND: Final[str] = "ArtSound"
|
6
|
+
MANUFACTURER_ARYLIC: Final[str] = "Arylic"
|
7
|
+
MANUFACTURER_IEAST: Final[str] = "iEAST"
|
8
|
+
MANUFACTURER_WIIM: Final[str] = "WiiM"
|
9
|
+
MANUFACTURER_GGMM: Final[str] = "GGMM"
|
10
|
+
MANUFACTURER_MEDION: Final[str] = "Medion"
|
11
|
+
MANUFACTURER_GENERIC: Final[str] = "Generic"
|
12
|
+
MODELS_ARTSOUND_SMART_ZONE4: Final[str] = "Smart Zone 4 AMP"
|
13
|
+
MODELS_ARTSOUND_SMART_HYDE: Final[str] = "Smart Hyde"
|
14
|
+
MODELS_ARYLIC_S50: Final[str] = "S50+"
|
15
|
+
MODELS_ARYLIC_S50_PRO: Final[str] = "S50 Pro"
|
16
|
+
MODELS_ARYLIC_A30: Final[str] = "A30"
|
17
|
+
MODELS_ARYLIC_A50: Final[str] = "A50"
|
18
|
+
MODELS_ARYLIC_A50S: Final[str] = "A50+"
|
19
|
+
MODELS_ARYLIC_UP2STREAM_AMP: Final[str] = "Up2Stream Amp 2.0"
|
20
|
+
MODELS_ARYLIC_UP2STREAM_AMP_2P1: Final[str] = "Up2Stream Amp 2.1"
|
21
|
+
MODELS_ARYLIC_UP2STREAM_AMP_V3: Final[str] = "Up2Stream Amp v3"
|
22
|
+
MODELS_ARYLIC_UP2STREAM_AMP_V4: Final[str] = "Up2Stream Amp v4"
|
23
|
+
MODELS_ARYLIC_UP2STREAM_PRO: Final[str] = "Up2Stream Pro v1"
|
24
|
+
MODELS_ARYLIC_UP2STREAM_PRO_V3: Final[str] = "Up2Stream Pro v3"
|
25
|
+
MODELS_ARYLIC_S10P: Final[str] = "Arylic S10+"
|
26
|
+
MODELS_ARYLIC_UP2STREAM_PLATE_AMP: Final[str] = "Up2Stream Plate Amp"
|
27
|
+
MODELS_IEAST_AUDIOCAST_M5: Final[str] = "AudioCast M5"
|
28
|
+
MODELS_WIIM_AMP: Final[str] = "WiiM Amp"
|
29
|
+
MODELS_WIIM_MINI: Final[str] = "WiiM Mini"
|
30
|
+
MODELS_WIIM_PRO: Final[str] = "WiiM Pro"
|
31
|
+
MODELS_GGMM_GGMM_E2: Final[str] = "GGMM E2"
|
32
|
+
MODELS_MEDION_MD_43970: Final[str] = "Life P66970 (MD 43970)"
|
33
|
+
MODELS_GENERIC: Final[str] = "Generic"
|
34
|
+
|
35
|
+
PROJECTID_LOOKUP: Final[dict[str, tuple[str, str]]] = {
|
36
|
+
"SMART_ZONE4_AMP": (MANUFACTURER_ARTSOUND, MODELS_ARTSOUND_SMART_ZONE4),
|
37
|
+
"SMART_HYDE": (MANUFACTURER_ARTSOUND, MODELS_ARTSOUND_SMART_HYDE),
|
38
|
+
"ARYLIC_S50": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_S50),
|
39
|
+
"RP0016_S50PRO_S": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_S50_PRO),
|
40
|
+
"RP0011_WB60_S": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_A30),
|
41
|
+
"X-50": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_A50),
|
42
|
+
"ARYLIC_A50S": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_A50S),
|
43
|
+
"RP0011_WB60": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_UP2STREAM_AMP),
|
44
|
+
"UP2STREAM_AMP_V3": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_UP2STREAM_AMP_V3),
|
45
|
+
"UP2STREAM_AMP_V4": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_UP2STREAM_AMP_V4),
|
46
|
+
"UP2STREAM_PRO_V3": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_UP2STREAM_PRO_V3),
|
47
|
+
"S10P_WIFI": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_S10P),
|
48
|
+
"ARYLIC_V20": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_UP2STREAM_PLATE_AMP),
|
49
|
+
"UP2STREAM_MINI_V3": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
50
|
+
"UP2STREAM_AMP_2P1": (MANUFACTURER_ARYLIC, MODELS_ARYLIC_UP2STREAM_AMP_2P1),
|
51
|
+
"RP0014_A50C_S": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
52
|
+
"ARYLIC_A30": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
53
|
+
"ARYLIC_SUBWOOFER": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
54
|
+
"ARYLIC_S50A": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
55
|
+
"RP0010_D5_S": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
56
|
+
"RP0001": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
57
|
+
"RP0013_WA31S": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
58
|
+
"RP0010_D5": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
59
|
+
"RP0013_WA31S_S": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
60
|
+
"RP0014_A50D_S": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
61
|
+
"ARYLIC_A50TE": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
62
|
+
"ARYLIC_A50N": (MANUFACTURER_ARYLIC, MODELS_GENERIC),
|
63
|
+
"iEAST-02": (MANUFACTURER_IEAST, MODELS_IEAST_AUDIOCAST_M5),
|
64
|
+
"WiiM_Amp_4layer": (MANUFACTURER_WIIM, MODELS_WIIM_AMP),
|
65
|
+
"WiiM_Pro_with_gc4a": (MANUFACTURER_WIIM, MODELS_WIIM_PRO),
|
66
|
+
"Muzo_Mini": (MANUFACTURER_WIIM, MODELS_WIIM_MINI),
|
67
|
+
"GGMM_E2A": (MANUFACTURER_GGMM, MODELS_GGMM_GGMM_E2),
|
68
|
+
"A16": (MANUFACTURER_MEDION, MODELS_MEDION_MD_43970),
|
69
|
+
}
|
70
|
+
|
71
|
+
|
72
|
+
def get_info_from_project(project: str) -> tuple[str, str]:
|
73
|
+
"""Get manufacturer and model info based on given project."""
|
74
|
+
return PROJECTID_LOOKUP.get(project, (MANUFACTURER_GENERIC, MODELS_GENERIC))
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: python_linkplay
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.2.0
|
4
4
|
Summary: A Python Library for Seamless LinkPlay Device Control
|
5
5
|
Author: Velleman Group nv
|
6
6
|
License: MIT
|
@@ -24,12 +24,13 @@ Requires-Dist: ruff>=0.5.4; extra == "testing"
|
|
24
24
|
Requires-Dist: tox>=4.6.0; extra == "testing"
|
25
25
|
Requires-Dist: typing-extensions>=4.6.3; extra == "testing"
|
26
26
|
Requires-Dist: pre-commit>=3.8.0; extra == "testing"
|
27
|
-
|
27
|
+
Dynamic: license-file
|
28
28
|
|
29
29
|
[](https://pypi.org/project/python-linkplay/)
|
30
30
|
[](https://github.com/velleman/python-linkplay/actions/workflows/release.yaml)
|
31
31
|
|
32
32
|
# python-linkplay
|
33
|
+
|
33
34
|
A Python Library for Seamless LinkPlay Device Control
|
34
35
|
|
35
36
|
## Intro
|
@@ -54,6 +55,9 @@ Welcome to python-linkplay, a powerful and user-friendly Python library designed
|
|
54
55
|
- https://developer.arylic.com/httpapi/
|
55
56
|
- http://airscope-audio.net/core2/pdf/airscope-module-http.pdf
|
56
57
|
- https://www.wiimhome.com/pdf/HTTP%20API%20for%20WiiM%20Mini.pdf
|
58
|
+
- https://www.wiimhome.com/pdf/HTTP%20API%20for%20WiiM%20Products.pdf
|
59
|
+
- https://github.com/DanBrezeanu/wiim-extended-http-api
|
60
|
+
- https://github.com/cvdlinden/wiim-httpapi
|
57
61
|
|
58
62
|
## Multiroom
|
59
63
|
|
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = '0.1.0'
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{python_linkplay-0.1.0 → python_linkplay-0.2.0}/src/python_linkplay.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|