python-linkplay 0.0.19__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- linkplay/__version__.py +1 -1
- linkplay/bridge.py +19 -3
- linkplay/consts.py +2 -0
- linkplay/discovery.py +16 -10
- linkplay/endpoint.py +4 -2
- {python_linkplay-0.0.19.dist-info → python_linkplay-0.1.0.dist-info}/METADATA +2 -2
- python_linkplay-0.1.0.dist-info/RECORD +15 -0
- {python_linkplay-0.0.19.dist-info → python_linkplay-0.1.0.dist-info}/WHEEL +1 -1
- python_linkplay-0.0.19.dist-info/RECORD +0 -15
- {python_linkplay-0.0.19.dist-info → python_linkplay-0.1.0.dist-info}/LICENSE +0 -0
- {python_linkplay-0.0.19.dist-info → python_linkplay-0.1.0.dist-info}/top_level.txt +0 -0
linkplay/__version__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '0.0
|
1
|
+
__version__ = '0.1.0'
|
linkplay/bridge.py
CHANGED
@@ -73,7 +73,17 @@ class LinkPlayDevice:
|
|
73
73
|
def eth(self) -> str | None:
|
74
74
|
"""Returns the ethernet address."""
|
75
75
|
eth2 = self.properties.get(DeviceAttribute.ETH2)
|
76
|
-
|
76
|
+
eth0 = self.properties.get(DeviceAttribute.ETH0)
|
77
|
+
for eth in [eth2, eth0]:
|
78
|
+
if eth == "0.0.0.0":
|
79
|
+
eth = None
|
80
|
+
return (
|
81
|
+
eth2
|
82
|
+
if eth2
|
83
|
+
else eth0
|
84
|
+
if eth0
|
85
|
+
else self.properties.get(DeviceAttribute.APCLI0)
|
86
|
+
)
|
77
87
|
|
78
88
|
async def timesync(self) -> None:
|
79
89
|
"""Sync the time."""
|
@@ -370,6 +380,8 @@ class LinkPlayMultiroom:
|
|
370
380
|
async def ungroup(self) -> None:
|
371
381
|
"""Ungroups the multiroom group."""
|
372
382
|
await self.leader.request(LinkPlayCommand.MULTIROOM_UNGROUP)
|
383
|
+
for follewer in self.followers:
|
384
|
+
follewer.multiroom = None
|
373
385
|
self.followers = []
|
374
386
|
|
375
387
|
async def add_follower(self, follower: LinkPlayBridge) -> None:
|
@@ -377,14 +389,18 @@ class LinkPlayMultiroom:
|
|
377
389
|
await follower.request(
|
378
390
|
LinkPlayCommand.MULTIROOM_JOIN.format(self.leader.device.eth)
|
379
391
|
) # type: ignore[str-format]
|
380
|
-
self.followers
|
392
|
+
if follower not in self.followers:
|
393
|
+
follower.multiroom = self
|
394
|
+
self.followers.append(follower)
|
381
395
|
|
382
396
|
async def remove_follower(self, follower: LinkPlayBridge) -> None:
|
383
397
|
"""Removes a follower from the multiroom group."""
|
384
398
|
await self.leader.request(
|
385
399
|
LinkPlayCommand.MULTIROOM_KICK.format(follower.device.eth)
|
386
400
|
) # type: ignore[str-format]
|
387
|
-
self.followers
|
401
|
+
if follower in self.followers:
|
402
|
+
follower.multiroom = None
|
403
|
+
self.followers.remove(follower)
|
388
404
|
|
389
405
|
async def set_volume(self, value: int) -> None:
|
390
406
|
"""Sets the volume for the multiroom group."""
|
linkplay/consts.py
CHANGED
@@ -145,6 +145,7 @@ class PlayingMode(StrEnum):
|
|
145
145
|
HTTP_MAX = "29"
|
146
146
|
ALARM = "30"
|
147
147
|
SPOTIFY = "31"
|
148
|
+
TIDAL = "32"
|
148
149
|
LINE_IN = "40"
|
149
150
|
BLUETOOTH = "41"
|
150
151
|
OPTICAL = "43"
|
@@ -179,6 +180,7 @@ PLAY_MODE_SEND_MAP: dict[PlayingMode, str] = { # case sensitive!
|
|
179
180
|
PlayingMode.UDISK: "udisk",
|
180
181
|
PlayingMode.ALARM: "Alarm",
|
181
182
|
PlayingMode.SPOTIFY: "Spotify",
|
183
|
+
PlayingMode.TIDAL: "Tidal",
|
182
184
|
PlayingMode.LINE_IN: "line-in",
|
183
185
|
PlayingMode.BLUETOOTH: "bluetooth",
|
184
186
|
PlayingMode.OPTICAL: "optical",
|
linkplay/discovery.py
CHANGED
@@ -21,7 +21,7 @@ async def linkplay_factory_bridge(
|
|
21
21
|
"""Attempts to create a LinkPlayBridge from the given IP address.
|
22
22
|
Returns None if the device is not an expected LinkPlay device."""
|
23
23
|
endpoint: LinkPlayApiEndpoint = LinkPlayApiEndpoint(
|
24
|
-
protocol="http", endpoint=ip_address, session=session
|
24
|
+
protocol="http", port=80, endpoint=ip_address, session=session
|
25
25
|
)
|
26
26
|
try:
|
27
27
|
return await linkplay_factory_bridge_endpoint(endpoint)
|
@@ -48,16 +48,22 @@ async def linkplay_factory_httpapi_bridge(
|
|
48
48
|
Attempts to use HTTPS first, then falls back to HTTP.
|
49
49
|
Raises LinkPlayRequestException if the device is not an expected LinkPlay device."""
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
except LinkPlayRequestException:
|
57
|
-
http_endpoint: LinkPlayApiEndpoint = LinkPlayApiEndpoint(
|
58
|
-
protocol="http", endpoint=ip_address, session=session
|
51
|
+
protocol_port_pairs = [("https", 443), ("https", 4443)]
|
52
|
+
|
53
|
+
for protocol, port in protocol_port_pairs:
|
54
|
+
endpoint: LinkPlayApiEndpoint = LinkPlayApiEndpoint(
|
55
|
+
protocol=protocol, port=port, endpoint=ip_address, session=session
|
59
56
|
)
|
60
|
-
|
57
|
+
|
58
|
+
try:
|
59
|
+
return await linkplay_factory_bridge_endpoint(endpoint)
|
60
|
+
except LinkPlayRequestException:
|
61
|
+
pass
|
62
|
+
|
63
|
+
http_endpoint: LinkPlayApiEndpoint = LinkPlayApiEndpoint(
|
64
|
+
protocol="http", port=80, endpoint=ip_address, session=session
|
65
|
+
)
|
66
|
+
return await linkplay_factory_bridge_endpoint(http_endpoint)
|
61
67
|
|
62
68
|
|
63
69
|
async def discover_linkplay_bridges(
|
linkplay/endpoint.py
CHANGED
@@ -30,12 +30,14 @@ class LinkPlayEndpoint(ABC):
|
|
30
30
|
class LinkPlayApiEndpoint(LinkPlayEndpoint):
|
31
31
|
"""Represents a LinkPlay HTTP API endpoint."""
|
32
32
|
|
33
|
-
def __init__(
|
33
|
+
def __init__(
|
34
|
+
self, *, protocol: str, port: int, endpoint: str, session: ClientSession
|
35
|
+
):
|
34
36
|
assert protocol in [
|
35
37
|
"http",
|
36
38
|
"https",
|
37
39
|
], "Protocol must be either 'http' or 'https'"
|
38
|
-
self._endpoint: str = f"{protocol}://{endpoint}"
|
40
|
+
self._endpoint: str = f"{protocol}://{endpoint}:{port}"
|
39
41
|
self._session: ClientSession = session
|
40
42
|
|
41
43
|
def to_dict(self):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: python_linkplay
|
3
|
-
Version: 0.0
|
3
|
+
Version: 0.1.0
|
4
4
|
Summary: A Python Library for Seamless LinkPlay Device Control
|
5
5
|
Author: Velleman Group nv
|
6
6
|
License: MIT
|
@@ -11,7 +11,7 @@ License-File: LICENSE
|
|
11
11
|
Requires-Dist: async-timeout>=4.0.3
|
12
12
|
Requires-Dist: aiohttp>=3.8.5
|
13
13
|
Requires-Dist: appdirs>=1.4.4
|
14
|
-
Requires-Dist:
|
14
|
+
Requires-Dist: async_upnp_client>=0.36.2
|
15
15
|
Requires-Dist: deprecated>=1.2.14
|
16
16
|
Requires-Dist: aiofiles>=23.1.0
|
17
17
|
Provides-Extra: testing
|
@@ -0,0 +1,15 @@
|
|
1
|
+
linkplay/__init__.py,sha256=y9ZehEq-KhS3cwn-PUpwVSJGfDUx7e5wf_G6guODcTk,56
|
2
|
+
linkplay/__main__.py,sha256=Wcza80QaWfOaHjyJEfQYhB9kiPLE0NOqIj4zVWv2Nqs,577
|
3
|
+
linkplay/__version__.py,sha256=IMjkMO3twhQzluVTo8Z6rE7Eg-9U79_LGKMcsWLKBkY,22
|
4
|
+
linkplay/bridge.py,sha256=Xj1YRz0oJJ41Bvjwfa-tMKQNVWgluADryFPTgD18qJM,15059
|
5
|
+
linkplay/consts.py,sha256=98VtgV4xOfXWr00yl1DwfmNxDI6Ul5fNPCyLp8ixggE,13535
|
6
|
+
linkplay/controller.py,sha256=IBFhnt-VhdIZnI_3OLU6hA8oQa9IZWY7-8cN0uCh3-w,3277
|
7
|
+
linkplay/discovery.py,sha256=NnkO9gknp3Cyff7830zBu1LwyhkkWCdhDbEDbAwF8D8,4610
|
8
|
+
linkplay/endpoint.py,sha256=PRf00v6sQI8hdTrMdg0qG0JUtsZFe-uCN0Lw1zqI1Lc,2491
|
9
|
+
linkplay/exceptions.py,sha256=Kow13uJPSL4y6rXMnkcl_Yp9wH1weOyKw_knd0p-Exc,173
|
10
|
+
linkplay/utils.py,sha256=Kmbzw8zC9mV89ZOC5-GNtbiLkgUkuvAEUcsJdRkSY-w,8485
|
11
|
+
python_linkplay-0.1.0.dist-info/LICENSE,sha256=bgEtxMyjEHX_4uwaAY3GCFTm234D4AOZ5dM15sk26ms,1073
|
12
|
+
python_linkplay-0.1.0.dist-info/METADATA,sha256=ZQ_QkjCcmkmTcBw80ZOVN2tNZi2lEWKZH4z3nFtYSq8,2987
|
13
|
+
python_linkplay-0.1.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
14
|
+
python_linkplay-0.1.0.dist-info/top_level.txt,sha256=CpSaOVPTzJf5TVIL7MrotSCR34gcIOQy-11l4zGmxxM,9
|
15
|
+
python_linkplay-0.1.0.dist-info/RECORD,,
|
@@ -1,15 +0,0 @@
|
|
1
|
-
linkplay/__init__.py,sha256=y9ZehEq-KhS3cwn-PUpwVSJGfDUx7e5wf_G6guODcTk,56
|
2
|
-
linkplay/__main__.py,sha256=Wcza80QaWfOaHjyJEfQYhB9kiPLE0NOqIj4zVWv2Nqs,577
|
3
|
-
linkplay/__version__.py,sha256=Wg0q75xR03Wgtr26_qt1wcsGMmTO6dHkia7eXfDFFKY,23
|
4
|
-
linkplay/bridge.py,sha256=e9ObGLhBw7BJp2hUdSXj3qvHh15rC5sSC-Q7vBnEvrQ,14575
|
5
|
-
linkplay/consts.py,sha256=5JQ-5CgmbPMBhrxhTb_0APnt1EnYhiNwsHn-68yDiTI,13486
|
6
|
-
linkplay/controller.py,sha256=IBFhnt-VhdIZnI_3OLU6hA8oQa9IZWY7-8cN0uCh3-w,3277
|
7
|
-
linkplay/discovery.py,sha256=XgzzsOkxtUPu5f7V1KTIqQWP6_UCQncpbWGaVN1lULU,4457
|
8
|
-
linkplay/endpoint.py,sha256=5Ybr54aroFVEZ6fnFYP41QAuSP7-J9qHYAzLod4S3KY,2459
|
9
|
-
linkplay/exceptions.py,sha256=Kow13uJPSL4y6rXMnkcl_Yp9wH1weOyKw_knd0p-Exc,173
|
10
|
-
linkplay/utils.py,sha256=Kmbzw8zC9mV89ZOC5-GNtbiLkgUkuvAEUcsJdRkSY-w,8485
|
11
|
-
python_linkplay-0.0.19.dist-info/LICENSE,sha256=bgEtxMyjEHX_4uwaAY3GCFTm234D4AOZ5dM15sk26ms,1073
|
12
|
-
python_linkplay-0.0.19.dist-info/METADATA,sha256=P00mdBXZWR0fccBk_aVAHGDuv2pQfyMDeCeTIJLo5p4,2988
|
13
|
-
python_linkplay-0.0.19.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
14
|
-
python_linkplay-0.0.19.dist-info/top_level.txt,sha256=CpSaOVPTzJf5TVIL7MrotSCR34gcIOQy-11l4zGmxxM,9
|
15
|
-
python_linkplay-0.0.19.dist-info/RECORD,,
|
File without changes
|
File without changes
|