soco-cli 0.4.73__tar.gz → 0.4.75__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.
- {soco-cli-0.4.73/soco_cli.egg-info → soco-cli-0.4.75}/PKG-INFO +1 -1
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/__init__.py +1 -1
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/alarms.py +12 -14
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/play_local_file.py +37 -7
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/speakers.py +7 -9
- {soco-cli-0.4.73 → soco-cli-0.4.75/soco_cli.egg-info}/PKG-INFO +1 -1
- {soco-cli-0.4.73 → soco-cli-0.4.75}/LICENSE +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/MANIFEST.in +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/PYPI_README.md +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/README.md +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/pyproject.toml +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/requirements.txt +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/setup.cfg +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/setup.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/__main__.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/action_processor.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/aliases.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/api.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/check_for_update.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/cmd_parser.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/http_api.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/interactive.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/keystroke_capture.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/m3u_parser.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/match_speaker_names.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/play_local_file_lists.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/sonos.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/sonos_discover.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/speaker_info.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/track_follow.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/utils.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli/wait_actions.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli.egg-info/SOURCES.txt +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli.egg-info/dependency_links.txt +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli.egg-info/entry_points.txt +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli.egg-info/requires.txt +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/soco_cli.egg-info/top_level.txt +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/tests/test_cli.py +0 -0
- {soco-cli-0.4.73 → soco-cli-0.4.75}/tests/test_utils.py +0 -0
|
@@ -53,20 +53,18 @@ def list_alarms(speaker, action, args, soco_function, use_local_speaker_list):
|
|
|
53
53
|
duration = alarm.duration.strftime("%H:%M")
|
|
54
54
|
else:
|
|
55
55
|
duration = "No Limit"
|
|
56
|
-
details.append(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
]
|
|
69
|
-
)
|
|
56
|
+
details.append([
|
|
57
|
+
alarm.alarm_id,
|
|
58
|
+
alarm.zone.player_name,
|
|
59
|
+
time,
|
|
60
|
+
duration,
|
|
61
|
+
alarm.recurrence,
|
|
62
|
+
convert_true_false(alarm.enabled),
|
|
63
|
+
title,
|
|
64
|
+
alarm.play_mode,
|
|
65
|
+
alarm.volume,
|
|
66
|
+
convert_true_false(alarm.include_linked_zones),
|
|
67
|
+
])
|
|
70
68
|
|
|
71
69
|
# Sort alarms by start time, room. Apply sorts in reverse order.
|
|
72
70
|
details.sort(key=lambda field: field[1]) # Room
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Plays files from the local filesystem."""
|
|
2
2
|
|
|
3
3
|
import functools
|
|
4
|
+
import http.client
|
|
4
5
|
import logging
|
|
5
6
|
import sys
|
|
6
7
|
import time
|
|
@@ -10,7 +11,7 @@ from ipaddress import IPv4Address, IPv4Network
|
|
|
10
11
|
from os import chdir, path
|
|
11
12
|
from socketserver import ThreadingMixIn
|
|
12
13
|
from threading import Thread
|
|
13
|
-
from typing import List,
|
|
14
|
+
from typing import List, Optional
|
|
14
15
|
|
|
15
16
|
import ifaddr # type: ignore
|
|
16
17
|
from RangeHTTPServer import RangeRequestHandler # type: ignore
|
|
@@ -93,7 +94,7 @@ class MyHTTPHandler(RangeRequestHandler):
|
|
|
93
94
|
|
|
94
95
|
def http_server(
|
|
95
96
|
server_ip: str, directory: str, filename: str, speaker_ips: List[str]
|
|
96
|
-
) ->
|
|
97
|
+
) -> Optional[ThreadedHTTPServer]:
|
|
97
98
|
# Set the directory from which to serve files, in the handler
|
|
98
99
|
# Set the specific filename and client IP that are authorised
|
|
99
100
|
handler = functools.partial(
|
|
@@ -122,18 +123,48 @@ def http_server(
|
|
|
122
123
|
return None
|
|
123
124
|
|
|
124
125
|
|
|
125
|
-
def get_server_ip(speaker: SoCo) ->
|
|
126
|
-
# Get
|
|
127
|
-
# on this host
|
|
126
|
+
def get_server_ip(speaker: SoCo) -> Optional[str]:
|
|
127
|
+
# Get the host IP address to use as a server IP for Sonos
|
|
128
|
+
# on this host.
|
|
129
|
+
|
|
128
130
|
adapters = ifaddr.get_adapters()
|
|
131
|
+
|
|
132
|
+
# First, try to find a host IP address in the same network as the speaker
|
|
129
133
|
for adapter in adapters:
|
|
130
134
|
for ip in adapter.ips:
|
|
131
|
-
if ip.is_IPv4:
|
|
135
|
+
if ip.is_IPv4 and ip.ip != "127.0.0.1":
|
|
136
|
+
logging.info(
|
|
137
|
+
"Checking if IP address '{}' is in target speaker's network".format(
|
|
138
|
+
ip.ip
|
|
139
|
+
)
|
|
140
|
+
)
|
|
132
141
|
network = IPv4Network(
|
|
133
142
|
ip.ip + "/" + str(ip.network_prefix), strict=False
|
|
134
143
|
)
|
|
135
144
|
if IPv4Address(speaker.ip_address) in network:
|
|
136
145
|
return ip.ip
|
|
146
|
+
|
|
147
|
+
# If that fails, try to find a host IP address that can reach the target speaker
|
|
148
|
+
for adapter in adapters:
|
|
149
|
+
for ip in adapter.ips:
|
|
150
|
+
if ip.is_IPv4 and ip.ip != "127.0.0.1":
|
|
151
|
+
try:
|
|
152
|
+
logging.info(
|
|
153
|
+
"Checking target speaker's reachability from IP address '{}'"
|
|
154
|
+
.format(ip.ip)
|
|
155
|
+
)
|
|
156
|
+
http_connection = http.client.HTTPConnection(
|
|
157
|
+
speaker.ip_address,
|
|
158
|
+
port=1400,
|
|
159
|
+
timeout=0.5,
|
|
160
|
+
source_address=(ip.ip, PORT_END),
|
|
161
|
+
)
|
|
162
|
+
http_connection.request("GET", "/status/info")
|
|
163
|
+
if http_connection.getresponse().status == 200:
|
|
164
|
+
return ip.ip
|
|
165
|
+
except:
|
|
166
|
+
continue
|
|
167
|
+
|
|
137
168
|
return None
|
|
138
169
|
|
|
139
170
|
|
|
@@ -186,7 +217,6 @@ def is_supported_type(filename: str) -> bool:
|
|
|
186
217
|
file_upper = filename.upper()
|
|
187
218
|
for file_type in SUPPORTED_TYPES:
|
|
188
219
|
if file_upper.endswith("." + file_type):
|
|
189
|
-
# Supported file type
|
|
190
220
|
return True
|
|
191
221
|
return False
|
|
192
222
|
|
|
@@ -305,15 +305,13 @@ class Speakers:
|
|
|
305
305
|
visible = "Visible"
|
|
306
306
|
else:
|
|
307
307
|
visible = "Hidden"
|
|
308
|
-
households[device.household_id].append(
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
)
|
|
316
|
-
)
|
|
308
|
+
households[device.household_id].append((
|
|
309
|
+
device.speaker_name,
|
|
310
|
+
device.ip_address,
|
|
311
|
+
device.model_name.replace("Sonos ", ""),
|
|
312
|
+
visible,
|
|
313
|
+
device.display_version,
|
|
314
|
+
))
|
|
317
315
|
num_devices += 1
|
|
318
316
|
|
|
319
317
|
headers = [
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|