PyChromecast 14.0.1__tar.gz → 14.0.3__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.
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/PKG-INFO +7 -1
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/PyChromecast.egg-info/PKG-INFO +7 -1
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/README.rst +6 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/const.py +1 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/plex.py +2 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/youtube.py +1 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/socket_client.py +34 -33
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pyproject.toml +1 -1
- PyChromecast-14.0.3/requirements.txt +3 -0
- PyChromecast-14.0.1/requirements.txt +0 -3
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/LICENSE +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/MANIFEST.in +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/PyChromecast.egg-info/SOURCES.txt +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/PyChromecast.egg-info/dependency_links.txt +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/PyChromecast.egg-info/not-zip-safe +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/PyChromecast.egg-info/requires.txt +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/PyChromecast.egg-info/top_level.txt +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/__init__.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/config.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/__init__.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/bbciplayer.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/bbcsounds.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/bubbleupnp.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/dashcast.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/homeassistant.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/homeassistant_media.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/media.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/multizone.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/nrkradio.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/nrktv.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/receiver.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/shaka.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/supla.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/controllers/yleareena.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/dial.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/discovery.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/error.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/generated/authority_keys_pb2.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/generated/authority_keys_pb2.pyi +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/generated/cast_channel_pb2.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/generated/cast_channel_pb2.pyi +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/generated/logging_pb2.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/generated/logging_pb2.pyi +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/generated/readme.txt +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/models.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/quick_play.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/pychromecast/response_handler.py +0 -0
- {PyChromecast-14.0.1 → PyChromecast-14.0.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyChromecast
|
|
3
|
-
Version: 14.0.
|
|
3
|
+
Version: 14.0.3
|
|
4
4
|
Summary: Python module to talk to Google Chromecast.
|
|
5
5
|
Author-email: Paulus Schoutsen <paulus@paulusschoutsen.nl>
|
|
6
6
|
Project-URL: Homepage, https://github.com/home-assistant-libs/pychromecast
|
|
@@ -192,3 +192,9 @@ work. Without him it would not have been possible!
|
|
|
192
192
|
|
|
193
193
|
.. _Linux style wildcard: http://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm
|
|
194
194
|
.. _Fred Clift: https://github.com/minektur
|
|
195
|
+
|
|
196
|
+
|ohf-logo|
|
|
197
|
+
|
|
198
|
+
.. |ohf-logo| image:: https://www.openhomefoundation.org/badges/pychromecast.png
|
|
199
|
+
:alt: PyChromecast - A library from the Open Home Foundation
|
|
200
|
+
:target: https://www.openhomefoundation.org/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyChromecast
|
|
3
|
-
Version: 14.0.
|
|
3
|
+
Version: 14.0.3
|
|
4
4
|
Summary: Python module to talk to Google Chromecast.
|
|
5
5
|
Author-email: Paulus Schoutsen <paulus@paulusschoutsen.nl>
|
|
6
6
|
Project-URL: Homepage, https://github.com/home-assistant-libs/pychromecast
|
|
@@ -192,3 +192,9 @@ work. Without him it would not have been possible!
|
|
|
192
192
|
|
|
193
193
|
.. _Linux style wildcard: http://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm
|
|
194
194
|
.. _Fred Clift: https://github.com/minektur
|
|
195
|
+
|
|
196
|
+
|ohf-logo|
|
|
197
|
+
|
|
198
|
+
.. |ohf-logo| image:: https://www.openhomefoundation.org/badges/pychromecast.png
|
|
199
|
+
:alt: PyChromecast - A library from the Open Home Foundation
|
|
200
|
+
:target: https://www.openhomefoundation.org/
|
|
@@ -175,3 +175,9 @@ work. Without him it would not have been possible!
|
|
|
175
175
|
|
|
176
176
|
.. _Linux style wildcard: http://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm
|
|
177
177
|
.. _Fred Clift: https://github.com/minektur
|
|
178
|
+
|
|
179
|
+
|ohf-logo|
|
|
180
|
+
|
|
181
|
+
.. |ohf-logo| image:: https://www.openhomefoundation.org/badges/pychromecast.png
|
|
182
|
+
:alt: PyChromecast - A library from the Open Home Foundation
|
|
183
|
+
:target: https://www.openhomefoundation.org/
|
|
@@ -43,6 +43,7 @@ CAST_TYPES = {
|
|
|
43
43
|
"nest audio": (CAST_TYPE_AUDIO, MF_GOOGLE),
|
|
44
44
|
"nest wifi point": (CAST_TYPE_AUDIO, MF_GOOGLE),
|
|
45
45
|
"bravia 4k vh2": (CAST_TYPE_CHROMECAST, MF_SONY),
|
|
46
|
+
"bravia 4k vh21": (CAST_TYPE_CHROMECAST, MF_SONY),
|
|
46
47
|
"C4A": (CAST_TYPE_AUDIO, MF_SONY),
|
|
47
48
|
"JBL Link 10": (CAST_TYPE_AUDIO, MF_JBL),
|
|
48
49
|
"JBL Link 20": (CAST_TYPE_AUDIO, MF_JBL),
|
|
@@ -108,6 +108,8 @@ def media_to_chromecast_command( # pylint: disable=invalid-name, too-many-local
|
|
|
108
108
|
dict: Returs a dict formatted correctly to start playback on a Chromecast.
|
|
109
109
|
"""
|
|
110
110
|
|
|
111
|
+
machineIdentifier = None
|
|
112
|
+
token = None
|
|
111
113
|
if media is not None:
|
|
112
114
|
# Lets set some params for the user if they use plexapi.
|
|
113
115
|
server: PlexServer = (
|
|
@@ -10,31 +10,31 @@ Without him this would not have been possible.
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
12
|
import abc
|
|
13
|
-
from dataclasses import dataclass
|
|
14
13
|
import errno
|
|
15
14
|
import json
|
|
16
15
|
import logging
|
|
17
|
-
import
|
|
16
|
+
import selectors
|
|
18
17
|
import socket
|
|
19
18
|
import ssl
|
|
20
19
|
import threading
|
|
21
20
|
import time
|
|
22
21
|
from collections import defaultdict
|
|
22
|
+
from dataclasses import dataclass
|
|
23
23
|
from struct import pack, unpack
|
|
24
24
|
|
|
25
25
|
import zeroconf
|
|
26
26
|
|
|
27
|
-
from .
|
|
27
|
+
from .const import MESSAGE_TYPE, REQUEST_ID, SESSION_ID
|
|
28
|
+
from .controllers import BaseController, CallbackType
|
|
28
29
|
from .controllers.media import MediaController
|
|
29
30
|
from .controllers.receiver import CastStatus, CastStatusListener, ReceiverController
|
|
30
|
-
from .const import MESSAGE_TYPE, REQUEST_ID, SESSION_ID
|
|
31
31
|
from .dial import get_host_from_service
|
|
32
32
|
from .error import (
|
|
33
33
|
ChromecastConnectionError,
|
|
34
34
|
ControllerNotRegistered,
|
|
35
|
-
UnsupportedNamespace,
|
|
36
35
|
NotConnected,
|
|
37
36
|
PyChromecastStopped,
|
|
37
|
+
UnsupportedNamespace,
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
# pylint: disable-next=no-name-in-module
|
|
@@ -64,8 +64,6 @@ CONNECTION_STATUS_FAILED = "FAILED"
|
|
|
64
64
|
CONNECTION_STATUS_FAILED_RESOLVE = "FAILED_RESOLVE"
|
|
65
65
|
# The socket connection was lost and needs to be retried
|
|
66
66
|
CONNECTION_STATUS_LOST = "LOST"
|
|
67
|
-
# Check for select poll method
|
|
68
|
-
SELECT_HAS_POLL = hasattr(select, "poll")
|
|
69
67
|
|
|
70
68
|
HB_PING_TIME = 10
|
|
71
69
|
HB_PONG_TIME = 10
|
|
@@ -215,6 +213,11 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
215
213
|
self.connecting = True
|
|
216
214
|
self.first_connection = True
|
|
217
215
|
self.socket: socket.socket | ssl.SSLSocket | None = None
|
|
216
|
+
self.selector = selectors.DefaultSelector()
|
|
217
|
+
self.wakeup_selector_key = self.selector.register(
|
|
218
|
+
self.socketpair[0], selectors.EVENT_READ
|
|
219
|
+
)
|
|
220
|
+
self.remote_selector_key: selectors.SelectorKey | None = None
|
|
218
221
|
|
|
219
222
|
# dict mapping namespace on Controller objects
|
|
220
223
|
self._handlers: dict[str, set[BaseController]] = defaultdict(set)
|
|
@@ -238,8 +241,10 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
238
241
|
tries = self.tries
|
|
239
242
|
|
|
240
243
|
if self.socket is not None:
|
|
244
|
+
self.selector.unregister(self.socket)
|
|
241
245
|
self.socket.close()
|
|
242
246
|
self.socket = None
|
|
247
|
+
self.remote_selector_key = None
|
|
243
248
|
|
|
244
249
|
# Make sure nobody is blocking.
|
|
245
250
|
for callback_function in self._request_callbacks.values():
|
|
@@ -288,10 +293,15 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
288
293
|
try:
|
|
289
294
|
if self.socket is not None:
|
|
290
295
|
# If we retry connecting, we need to clean up the socket again
|
|
291
|
-
self.
|
|
296
|
+
self.selector.unregister(self.socket) # type: ignore[unreachable]
|
|
297
|
+
self.socket.close()
|
|
292
298
|
self.socket = None
|
|
299
|
+
self.remote_selector_key = None
|
|
293
300
|
|
|
294
301
|
self.socket = new_socket()
|
|
302
|
+
self.remote_selector_key = self.selector.register(
|
|
303
|
+
self.socket, selectors.EVENT_READ
|
|
304
|
+
)
|
|
295
305
|
self.socket.settimeout(self.timeout)
|
|
296
306
|
self._report_connection_status(
|
|
297
307
|
ConnectionStatus(
|
|
@@ -559,20 +569,8 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
559
569
|
assert self.socket is not None
|
|
560
570
|
|
|
561
571
|
# poll the socket, as well as the socketpair to allow us to be interrupted
|
|
562
|
-
rlist = [self.socket, self.socketpair[0]]
|
|
563
572
|
try:
|
|
564
|
-
|
|
565
|
-
# Map file descriptors to socket objects because select.select does not support fd > 1024
|
|
566
|
-
# https://stackoverflow.com/questions/14250751/how-to-increase-filedescriptors-range-in-python-select
|
|
567
|
-
fd_to_socket = {rlist_item.fileno(): rlist_item for rlist_item in rlist}
|
|
568
|
-
|
|
569
|
-
poll_obj = select.poll()
|
|
570
|
-
for poll_fd in rlist:
|
|
571
|
-
poll_obj.register(poll_fd, select.POLLIN)
|
|
572
|
-
poll_result = poll_obj.poll(timeout * 1000) # timeout in milliseconds
|
|
573
|
-
can_read = [fd_to_socket[fd] for fd, _status in poll_result]
|
|
574
|
-
else:
|
|
575
|
-
can_read, _, _ = select.select(rlist, [], [], timeout)
|
|
573
|
+
ready = self.selector.select(timeout)
|
|
576
574
|
except (ValueError, OSError) as exc:
|
|
577
575
|
self.logger.error(
|
|
578
576
|
"[%s(%s):%s] Error in select call: %s",
|
|
@@ -584,9 +582,10 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
584
582
|
self._force_recon = True
|
|
585
583
|
return 0
|
|
586
584
|
|
|
585
|
+
can_read = {key for key, _ in ready}
|
|
587
586
|
# read message from chromecast
|
|
588
587
|
message = None
|
|
589
|
-
if self.
|
|
588
|
+
if self.remote_selector_key in can_read and not self._force_recon:
|
|
590
589
|
try:
|
|
591
590
|
message = self._read_message()
|
|
592
591
|
except InterruptLoop as exc:
|
|
@@ -611,18 +610,17 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
611
610
|
if self.stop.is_set():
|
|
612
611
|
return 1
|
|
613
612
|
raise
|
|
614
|
-
except socket.error:
|
|
613
|
+
except socket.error as exc:
|
|
615
614
|
self._force_recon = True
|
|
616
615
|
self.logger.error(
|
|
617
|
-
"[%s(%s):%s] Error reading from socket
|
|
616
|
+
"[%s(%s):%s] Error reading from socket: %s",
|
|
618
617
|
self.fn or "",
|
|
619
618
|
self.host,
|
|
620
619
|
self.port,
|
|
620
|
+
exc,
|
|
621
621
|
)
|
|
622
|
-
else:
|
|
623
|
-
data = _dict_from_message_payload(message)
|
|
624
622
|
|
|
625
|
-
if self.
|
|
623
|
+
if self.wakeup_selector_key in can_read:
|
|
626
624
|
# Clear the socket's buffer
|
|
627
625
|
self.socketpair[0].recv(128)
|
|
628
626
|
|
|
@@ -635,6 +633,7 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
635
633
|
return 0
|
|
636
634
|
|
|
637
635
|
# See if any handlers will accept this message
|
|
636
|
+
data = _dict_from_message_payload(message)
|
|
638
637
|
self._route_message(message, data)
|
|
639
638
|
|
|
640
639
|
if REQUEST_ID in data and data[REQUEST_ID] in self._request_callbacks:
|
|
@@ -652,8 +651,8 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
652
651
|
# check if connection is expired
|
|
653
652
|
reset = False
|
|
654
653
|
if self._force_recon:
|
|
655
|
-
self.logger.
|
|
656
|
-
"[%s(%s):%s]
|
|
654
|
+
self.logger.debug(
|
|
655
|
+
"[%s(%s):%s] Forced reconnection",
|
|
657
656
|
self.fn or "",
|
|
658
657
|
self.host,
|
|
659
658
|
self.port,
|
|
@@ -661,7 +660,7 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
661
660
|
reset = True
|
|
662
661
|
|
|
663
662
|
elif self.heartbeat_controller.is_expired():
|
|
664
|
-
self.logger.
|
|
663
|
+
self.logger.info(
|
|
665
664
|
"[%s(%s):%s] Heartbeat timeout, resetting connection",
|
|
666
665
|
self.fn or "",
|
|
667
666
|
self.host,
|
|
@@ -767,6 +766,7 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
767
766
|
|
|
768
767
|
self.socketpair[0].close()
|
|
769
768
|
self.socketpair[1].close()
|
|
769
|
+
self.selector.close()
|
|
770
770
|
|
|
771
771
|
self.connecting = True
|
|
772
772
|
|
|
@@ -897,17 +897,18 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
897
897
|
else:
|
|
898
898
|
callback_function(True, None)
|
|
899
899
|
self.socket.sendall(be_size + msg.SerializeToString())
|
|
900
|
-
except socket.error:
|
|
900
|
+
except socket.error as exc:
|
|
901
901
|
if callback_function:
|
|
902
902
|
callback_function(False, None)
|
|
903
903
|
if not no_add_request_id:
|
|
904
904
|
self._request_callbacks.pop(request_id, None)
|
|
905
905
|
self._force_recon = True
|
|
906
|
-
self.logger.
|
|
907
|
-
"[%s(%s):%s] Error writing to socket
|
|
906
|
+
self.logger.warning(
|
|
907
|
+
"[%s(%s):%s] Error writing to socket: %s",
|
|
908
908
|
self.fn or "",
|
|
909
909
|
self.host,
|
|
910
910
|
self.port,
|
|
911
|
+
exc,
|
|
911
912
|
)
|
|
912
913
|
else:
|
|
913
914
|
if callback_function:
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|