spotifywebapiPython 1.0.243__py3-none-any.whl → 1.0.244__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.
- spotifywebapipython/const.py +1 -1
- spotifywebapipython/docs/__init__.html +9 -2
- spotifywebapipython/docs/index.html +2 -2
- spotifywebapipython/docs/search.js +1 -1
- spotifywebapipython/docs/spotifywebapipython/const.html +3 -3
- spotifywebapipython/docs/spotifywebapipython/saappmessages.html +2 -2
- spotifywebapipython/docs/spotifywebapipython/sautils.html +2 -2
- spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html +2 -2
- spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html +2 -2
- spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html +2 -2
- spotifywebapipython/docs/spotifywebapipython/spotifyclient.html +2 -2
- spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html +2 -2
- spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html +2 -2
- spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html +2 -2
- spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html +2 -2
- spotifywebapipython/spotifyconnect/spotifyconnectdirectorytask.py +228 -76
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastcontroller.py +2 -2
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonecontrollerlistener.py +247 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonemanagerlistener.py +384 -0
- {spotifywebapipython-1.0.243.dist-info → spotifywebapipython-1.0.244.dist-info}/METADATA +1 -1
- {spotifywebapipython-1.0.243.dist-info → spotifywebapipython-1.0.244.dist-info}/RECORD +24 -23
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonelistener.py +0 -212
- {spotifywebapipython-1.0.243.dist-info → spotifywebapipython-1.0.244.dist-info}/LICENSE +0 -0
- {spotifywebapipython-1.0.243.dist-info → spotifywebapipython-1.0.244.dist-info}/WHEEL +0 -0
- {spotifywebapipython-1.0.243.dist-info → spotifywebapipython-1.0.244.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# external package imports.
|
|
2
|
+
from pychromecast.controllers.multizone import MultizoneController, MultiZoneControllerListener
|
|
3
|
+
from pychromecast.dial import MultizoneStatus, get_multizone_status
|
|
4
|
+
from pychromecast import Chromecast
|
|
5
|
+
import pychromecast
|
|
6
|
+
import threading
|
|
7
|
+
from uuid import UUID
|
|
8
|
+
from zeroconf import Zeroconf
|
|
9
|
+
|
|
10
|
+
# our package imports.
|
|
11
|
+
from spotifywebapipython.models import SpotifyConnectDevice, ZeroconfDiscoveryResult
|
|
12
|
+
# note - cannot reference `SpotifyConnectDirectoryTask` due to circular import!
|
|
13
|
+
# from .spotifyconnectdirectorytask import SpotifyConnectDirectoryTask
|
|
14
|
+
|
|
15
|
+
# get smartinspect logger reference; create a new session for this module name.
|
|
16
|
+
from smartinspectpython.siauto import SIAuto, SILevel, SISession, SIMethodParmListContext, SIColors
|
|
17
|
+
import logging
|
|
18
|
+
|
|
19
|
+
_logsi:SISession = SIAuto.Si.GetSession(__name__)
|
|
20
|
+
if (_logsi == None):
|
|
21
|
+
_logsi = SIAuto.Si.AddSession(__name__, True)
|
|
22
|
+
_logsi.SystemLogger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SpotifyConnectZeroconfCastMultiZoneControllerListener(MultiZoneControllerListener):
|
|
26
|
+
"""
|
|
27
|
+
Google Chromecast Zeroconf MultiZone Listener class.
|
|
28
|
+
|
|
29
|
+
Listens for Chromecast device multi-zone status updates for devices that
|
|
30
|
+
support multi-zone / group functionality.
|
|
31
|
+
|
|
32
|
+
This class should only be added as a listener to Chromecast group devices.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
UNHANDLED_EXCEPTION_MSG:str = "Unhandled exception occured while processing Chromecast MultiZoneController notification (%s)"
|
|
36
|
+
"""
|
|
37
|
+
Unhandled exception occured while processing Chromecast MultiZoneController notification (%s)
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
parentDirectory,
|
|
43
|
+
zeroconfInstance:Zeroconf,
|
|
44
|
+
zeroconf_RLock:threading.RLock,
|
|
45
|
+
castMultizoneController:MultizoneController,
|
|
46
|
+
castDevice:Chromecast,
|
|
47
|
+
) -> None:
|
|
48
|
+
"""
|
|
49
|
+
Initializes a new instance of the class.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
parentDirectory (SpotifyConnectDirectoryTask):
|
|
53
|
+
Parent SpotifyConnectDirectoryTask instance.
|
|
54
|
+
zeroconfInstance (Zeroconf):
|
|
55
|
+
Zeroconf instance used to query zeroconf.
|
|
56
|
+
zeroconf_RLock (threading.RLock):
|
|
57
|
+
Lock object used to enforce thread-safe updates.
|
|
58
|
+
castMultizoneController (MultizoneController)
|
|
59
|
+
MultizoneController parent instance.
|
|
60
|
+
castDevice (Chromecast):
|
|
61
|
+
Chromecast device object.
|
|
62
|
+
"""
|
|
63
|
+
# invoke base class method.
|
|
64
|
+
super().__init__()
|
|
65
|
+
|
|
66
|
+
# initialize storage.
|
|
67
|
+
self._CastMultizoneController:MultizoneController = castMultizoneController
|
|
68
|
+
self._CastDevice = castDevice
|
|
69
|
+
""" Cast group device that received the multizone notification. """
|
|
70
|
+
self._ParentDirectory = parentDirectory
|
|
71
|
+
self._ZeroconfInstance:Zeroconf = zeroconfInstance
|
|
72
|
+
self._Zeroconf_RLock:threading.RLock = zeroconf_RLock
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def multizone_member_added(
|
|
76
|
+
self,
|
|
77
|
+
member_uuid:str,
|
|
78
|
+
) -> None:
|
|
79
|
+
"""
|
|
80
|
+
Called when cast device identified by `member_uuid` has been added to a group.
|
|
81
|
+
"""
|
|
82
|
+
# use lock, as multiple threads could be calling this method simultaneously.
|
|
83
|
+
with self._Zeroconf_RLock:
|
|
84
|
+
|
|
85
|
+
# copy passed parameters to thread-safe storage.
|
|
86
|
+
argsMemberUuid:UUID = member_uuid
|
|
87
|
+
|
|
88
|
+
apiMethodName:str = "multizone_member_added (MultiZoneControllerListener)"
|
|
89
|
+
apiMethodParms:SIMethodParmListContext = None
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
|
|
93
|
+
# trace.
|
|
94
|
+
apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
|
|
95
|
+
apiMethodParms.AppendKeyValue("member_uuid", argsMemberUuid)
|
|
96
|
+
_logsi.LogMethodParmList(SILevel.Debug, "Chromecast multizone controller notification was received for Cast device key \"%s\"" % (argsMemberUuid), apiMethodParms, colorValue=SIColors.Lavender)
|
|
97
|
+
|
|
98
|
+
# trace.
|
|
99
|
+
if (_logsi.IsOn(SILevel.Verbose)):
|
|
100
|
+
|
|
101
|
+
# get device instance.
|
|
102
|
+
scDevice:SpotifyConnectDevice = self._ParentDirectory._SpotifyConnectDevices.GetDeviceByDiscoveryKey(str(argsMemberUuid))
|
|
103
|
+
if (scDevice is None):
|
|
104
|
+
|
|
105
|
+
# trace.
|
|
106
|
+
_logsi.LogVerbose("Could not find SpotifyConnectDevices instance for Cast device key: \"%s\"" % (str(argsMemberUuid)), colorValue=SIColors.Lavender)
|
|
107
|
+
|
|
108
|
+
else:
|
|
109
|
+
|
|
110
|
+
_logsi.LogVerbose("Chromecast multizone controller for group \"%s\" added member device: %s" % (self._CastDevice.cast_info.friendly_name, scDevice.Title), colorValue=SIColors.Lavender)
|
|
111
|
+
|
|
112
|
+
# get multizone controller reference for the group device, so we can get it's members.
|
|
113
|
+
castMultizoneController:MultizoneController = self._ParentDirectory._CastMultiZoneControllers.get(str(self._CastDevice.uuid), None)
|
|
114
|
+
if (castMultizoneController is not None):
|
|
115
|
+
membersSummary:list[str] = []
|
|
116
|
+
for member in castMultizoneController.members:
|
|
117
|
+
scMemberDevice:SpotifyConnectDevice = self._ParentDirectory._SpotifyConnectDevices.GetDeviceByDiscoveryKey(member)
|
|
118
|
+
if (scMemberDevice is None):
|
|
119
|
+
membersSummary.append(str(member))
|
|
120
|
+
else:
|
|
121
|
+
membersSummary.append("%s [ip=%s]" % (scMemberDevice.Title, scMemberDevice.DiscoveryResult.HostIpTitle))
|
|
122
|
+
_logsi.LogArray(SILevel.Verbose, "Chromecast multizone controller members for group: \"%s\" (count=%d)" % (self._CastDevice.cast_info.friendly_name, len(membersSummary)), membersSummary, colorValue=SIColors.Lavender)
|
|
123
|
+
|
|
124
|
+
except Exception as ex:
|
|
125
|
+
|
|
126
|
+
# trace.
|
|
127
|
+
_logsi.LogException(SpotifyConnectZeroconfCastMultiZoneControllerListener.UNHANDLED_EXCEPTION_MSG % (apiMethodName), ex, logToSystemLogger=False)
|
|
128
|
+
|
|
129
|
+
# ignore exception, as nothing can be done about it.
|
|
130
|
+
|
|
131
|
+
finally:
|
|
132
|
+
|
|
133
|
+
# trace.
|
|
134
|
+
_logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def multizone_member_removed(
|
|
138
|
+
self,
|
|
139
|
+
member_uuid,
|
|
140
|
+
) -> None:
|
|
141
|
+
"""
|
|
142
|
+
Called when cast device identified by `member_uuid` has been removed from a group.
|
|
143
|
+
"""
|
|
144
|
+
# use lock, as multiple threads could be calling this method simultaneously.
|
|
145
|
+
with self._Zeroconf_RLock:
|
|
146
|
+
|
|
147
|
+
# copy passed parameters to thread-safe storage.
|
|
148
|
+
argsMemberUuid:UUID = member_uuid
|
|
149
|
+
|
|
150
|
+
apiMethodName:str = "multizone_member_removed (MultiZoneControllerListener)"
|
|
151
|
+
apiMethodParms:SIMethodParmListContext = None
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
|
|
155
|
+
# trace.
|
|
156
|
+
apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
|
|
157
|
+
apiMethodParms.AppendKeyValue("member_uuid", argsMemberUuid)
|
|
158
|
+
_logsi.LogMethodParmList(SILevel.Debug, "Chromecast multizone controller notification was received for Cast device key \"%s\"" % (argsMemberUuid), apiMethodParms, colorValue=SIColors.Lavender)
|
|
159
|
+
|
|
160
|
+
# trace.
|
|
161
|
+
if (_logsi.IsOn(SILevel.Verbose)):
|
|
162
|
+
|
|
163
|
+
# get device instance.
|
|
164
|
+
scDevice:SpotifyConnectDevice = self._ParentDirectory._SpotifyConnectDevices.GetDeviceByDiscoveryKey(str(argsMemberUuid))
|
|
165
|
+
if (scDevice is None):
|
|
166
|
+
|
|
167
|
+
# trace.
|
|
168
|
+
_logsi.LogVerbose("Could not find SpotifyConnectDevices instance for Cast device key: \"%s\"" % (str(argsMemberUuid)), colorValue=SIColors.Lavender)
|
|
169
|
+
|
|
170
|
+
else:
|
|
171
|
+
|
|
172
|
+
_logsi.LogVerbose("Chromecast multizone controller for group \"%s\" removed member device: %s" % (self._CastDevice.cast_info.friendly_name, scDevice.Title), colorValue=SIColors.Lavender)
|
|
173
|
+
|
|
174
|
+
# get multizone controller reference for the group device, so we can get it's members.
|
|
175
|
+
castMultizoneController:MultizoneController = self._ParentDirectory._CastMultiZoneControllers.get(str(self._CastDevice.uuid), None)
|
|
176
|
+
if (castMultizoneController is not None):
|
|
177
|
+
membersSummary:list[str] = []
|
|
178
|
+
for member in castMultizoneController.members:
|
|
179
|
+
scMemberDevice:SpotifyConnectDevice = self._ParentDirectory._SpotifyConnectDevices.GetDeviceByDiscoveryKey(member)
|
|
180
|
+
if (scMemberDevice is None):
|
|
181
|
+
membersSummary.append(str(member))
|
|
182
|
+
else:
|
|
183
|
+
membersSummary.append("%s [ip=%s]" % (scMemberDevice.Title, scMemberDevice.DiscoveryResult.HostIpTitle))
|
|
184
|
+
_logsi.LogArray(SILevel.Verbose, "Chromecast multizone controller members for group: \"%s\" (count=%d)" % (self._CastDevice.cast_info.friendly_name, len(membersSummary)), membersSummary, colorValue=SIColors.Lavender)
|
|
185
|
+
|
|
186
|
+
except Exception as ex:
|
|
187
|
+
|
|
188
|
+
# trace.
|
|
189
|
+
_logsi.LogException(SpotifyConnectZeroconfCastMultiZoneControllerListener.UNHANDLED_EXCEPTION_MSG % (apiMethodName), ex, logToSystemLogger=False)
|
|
190
|
+
|
|
191
|
+
# ignore exception, as nothing can be done about it.
|
|
192
|
+
|
|
193
|
+
finally:
|
|
194
|
+
|
|
195
|
+
# trace.
|
|
196
|
+
_logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def multizone_status_received(
|
|
200
|
+
self,
|
|
201
|
+
) -> None:
|
|
202
|
+
"""
|
|
203
|
+
Called when Multizone status has been updated.
|
|
204
|
+
"""
|
|
205
|
+
# use lock, as multiple threads could be calling this method simultaneously.
|
|
206
|
+
with self._Zeroconf_RLock:
|
|
207
|
+
|
|
208
|
+
# copy passed parameters to thread-safe storage.
|
|
209
|
+
# n/a
|
|
210
|
+
|
|
211
|
+
apiMethodName:str = "multizone_status_received (MultiZoneControllerListener)"
|
|
212
|
+
apiMethodParms:SIMethodParmListContext = None
|
|
213
|
+
|
|
214
|
+
try:
|
|
215
|
+
|
|
216
|
+
# trace.
|
|
217
|
+
apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
|
|
218
|
+
_logsi.LogMethodParmList(SILevel.Debug, "Chromecast multizone controller status has been updated for group: \"%s\"" % (self._CastDevice.cast_info.friendly_name), apiMethodParms, colorValue=SIColors.Lavender)
|
|
219
|
+
|
|
220
|
+
# trace.
|
|
221
|
+
if (_logsi.IsOn(SILevel.Verbose)):
|
|
222
|
+
|
|
223
|
+
# trace.
|
|
224
|
+
_logsi.LogObject(SILevel.Verbose, "Chromecast multizone controller group status: \"%s\"" % (self._CastDevice.cast_info.friendly_name), self._CastDevice.status, colorValue=SIColors.Lavender)
|
|
225
|
+
|
|
226
|
+
# build member list with friendly names.
|
|
227
|
+
membersSummary:list[str] = []
|
|
228
|
+
member:str = None
|
|
229
|
+
for member in self._CastMultizoneController.members:
|
|
230
|
+
scMemberDevice:SpotifyConnectDevice = self._ParentDirectory._SpotifyConnectDevices.GetDeviceByDiscoveryKey(member)
|
|
231
|
+
if (scMemberDevice is None):
|
|
232
|
+
membersSummary.append(str(member))
|
|
233
|
+
else:
|
|
234
|
+
membersSummary.append("%s [ip=%s]" % (scMemberDevice.Title, scMemberDevice.DiscoveryResult.HostIpTitle))
|
|
235
|
+
_logsi.LogArray(SILevel.Verbose, "Chromecast multizone controller group members: \"%s\" (count=%d)" % (self._CastDevice.cast_info.friendly_name, len(membersSummary)), membersSummary, colorValue=SIColors.Lavender)
|
|
236
|
+
|
|
237
|
+
except Exception as ex:
|
|
238
|
+
|
|
239
|
+
# trace.
|
|
240
|
+
_logsi.LogException(SpotifyConnectZeroconfCastMultiZoneControllerListener.UNHANDLED_EXCEPTION_MSG % (apiMethodName), ex, logToSystemLogger=False)
|
|
241
|
+
|
|
242
|
+
# ignore exception, as nothing can be done about it.
|
|
243
|
+
|
|
244
|
+
finally:
|
|
245
|
+
|
|
246
|
+
# trace.
|
|
247
|
+
_logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
|
|
2
|
+
# external package imports.
|
|
3
|
+
from pychromecast.controllers.media import MediaStatus
|
|
4
|
+
from pychromecast.controllers.multizone import MultizoneController, MultizoneManager, MultiZoneManagerListener, GroupInfo
|
|
5
|
+
from pychromecast.controllers.receiver import CastStatus
|
|
6
|
+
from pychromecast.dial import MultizoneStatus, get_multizone_status
|
|
7
|
+
from pychromecast import Chromecast
|
|
8
|
+
import pychromecast
|
|
9
|
+
import threading
|
|
10
|
+
from uuid import UUID
|
|
11
|
+
from zeroconf import Zeroconf
|
|
12
|
+
|
|
13
|
+
# our package imports.
|
|
14
|
+
from spotifywebapipython.models import SpotifyConnectDevice
|
|
15
|
+
# note - cannot reference `SpotifyConnectDirectoryTask` due to circular import!
|
|
16
|
+
# from .spotifyconnectdirectorytask import SpotifyConnectDirectoryTask
|
|
17
|
+
|
|
18
|
+
# get smartinspect logger reference; create a new session for this module name.
|
|
19
|
+
from smartinspectpython.siauto import SIAuto, SILevel, SISession, SIMethodParmListContext, SIColors
|
|
20
|
+
import logging
|
|
21
|
+
|
|
22
|
+
_logsi:SISession = SIAuto.Si.GetSession(__name__)
|
|
23
|
+
if (_logsi == None):
|
|
24
|
+
_logsi = SIAuto.Si.AddSession(__name__, True)
|
|
25
|
+
_logsi.SystemLogger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SpotifyConnectZeroconfCastMultiZoneManagerListener(MultiZoneManagerListener):
|
|
29
|
+
"""
|
|
30
|
+
Google Chromecast Zeroconf MultiZone Listener class.
|
|
31
|
+
|
|
32
|
+
Listens for Chromecast device multi-zone status updates for devices that
|
|
33
|
+
support multi-zone / group functionality.
|
|
34
|
+
|
|
35
|
+
This class should be added as a listener to all Chromecast devices.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
UNHANDLED_EXCEPTION_MSG:str = "Unhandled exception occured while processing Chromecast MultizoneManager notification (%s)"
|
|
39
|
+
"""
|
|
40
|
+
Unhandled exception occured while processing Chromecast MultizoneManager notification (%s)
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
parentDirectory,
|
|
46
|
+
zeroconfInstance:Zeroconf,
|
|
47
|
+
zeroconf_RLock:threading.RLock,
|
|
48
|
+
castMultizoneManager:MultizoneManager,
|
|
49
|
+
castDevice:Chromecast,
|
|
50
|
+
) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Initializes a new instance of the class.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
parentDirectory (SpotifyConnectDirectoryTask):
|
|
56
|
+
Parent SpotifyConnectDirectoryTask instance.
|
|
57
|
+
zeroconfInstance (Zeroconf):
|
|
58
|
+
Zeroconf instance used to query zeroconf.
|
|
59
|
+
zeroconf_RLock (threading.RLock):
|
|
60
|
+
Lock object used to enforce thread-safe updates.
|
|
61
|
+
castMultizoneManager (MultizoneManager)
|
|
62
|
+
MultizoneManager parent instance.
|
|
63
|
+
castDevice (Chromecast):
|
|
64
|
+
Chromecast device object.
|
|
65
|
+
"""
|
|
66
|
+
# invoke base class method.
|
|
67
|
+
super().__init__()
|
|
68
|
+
|
|
69
|
+
# initialize storage.
|
|
70
|
+
self._CastMultizoneManager:MultizoneManager = castMultizoneManager
|
|
71
|
+
self._CastDevice = castDevice
|
|
72
|
+
""" Cast group device that received the multizone notification. """
|
|
73
|
+
self._ParentDirectory = parentDirectory
|
|
74
|
+
self._ZeroconfInstance:Zeroconf = zeroconfInstance
|
|
75
|
+
self._Zeroconf_RLock:threading.RLock = zeroconf_RLock
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def added_to_multizone(
|
|
79
|
+
self,
|
|
80
|
+
group_uuid:str,
|
|
81
|
+
) -> None:
|
|
82
|
+
"""
|
|
83
|
+
Called when cast has been added to group identified by group_uuid.
|
|
84
|
+
"""
|
|
85
|
+
# use lock, as multiple threads could be calling this method simultaneously.
|
|
86
|
+
with self._Zeroconf_RLock:
|
|
87
|
+
|
|
88
|
+
# copy passed parameters to thread-safe storage.
|
|
89
|
+
argsGroupUuid:UUID = group_uuid
|
|
90
|
+
|
|
91
|
+
apiMethodName:str = "added_to_multizone (MultiZoneManagerListener)"
|
|
92
|
+
apiMethodParms:SIMethodParmListContext = None
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
|
|
96
|
+
# trace.
|
|
97
|
+
apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
|
|
98
|
+
apiMethodParms.AppendKeyValue("group_uuid", argsGroupUuid)
|
|
99
|
+
_logsi.LogMethodParmList(SILevel.Debug, "Chromecast multizone manager notification was received for group \"%s\"" % (argsGroupUuid), apiMethodParms, colorValue=SIColors.Lavender)
|
|
100
|
+
|
|
101
|
+
# trace.
|
|
102
|
+
if (_logsi.IsOn(SILevel.Verbose)):
|
|
103
|
+
|
|
104
|
+
# get group device instance.
|
|
105
|
+
scDevice:SpotifyConnectDevice = self._ParentDirectory._SpotifyConnectDevices.GetDeviceByDiscoveryKey(str(argsGroupUuid))
|
|
106
|
+
if (scDevice is None):
|
|
107
|
+
|
|
108
|
+
# trace.
|
|
109
|
+
_logsi.LogVerbose("Could not find SpotifyConnectDevices instance for Cast device key: \"%s\"" % (str(argsGroupUuid)), colorValue=SIColors.Lavender)
|
|
110
|
+
|
|
111
|
+
else:
|
|
112
|
+
|
|
113
|
+
# trace.
|
|
114
|
+
_logsi.LogVerbose("Chromecast multizone manager added device \"%s\" to multizone group %s" % (self._CastDevice.cast_info.friendly_name, scDevice.Title), colorValue=SIColors.Lavender)
|
|
115
|
+
|
|
116
|
+
# # get the current multizone status.
|
|
117
|
+
# castMultiZoneStatus:MultizoneStatus = get_multizone_status(scDevice.DiscoveryResult.HostIpAddress, self._CastDevice.cast_info.services, self._ZeroconfInstance, 5)
|
|
118
|
+
# _logsi.LogObject(SILevel.Verbose, "Chromecast multizone manager status for group: %s [%s] (get_multizone_status)" % (scDevice.Title, scDevice.DiscoveryResult.HostIpTitle), castMultiZoneStatus, colorValue=SIColors.Lavender)
|
|
119
|
+
|
|
120
|
+
# # build member list with friendly names.
|
|
121
|
+
# result:list[str] = []
|
|
122
|
+
# member:GroupInfo = None
|
|
123
|
+
# for key, member in self._CastMultizoneManager._groups.items():
|
|
124
|
+
# memberName:str = member["chromecast"].cast_info.friendly_name
|
|
125
|
+
# result.append(memberName + ": " + str(member))
|
|
126
|
+
# _logsi.LogArray(SILevel.Verbose, "Chromecast multizone group \"%s\" groups (count=%d)" % (scDevice.Title, len(result)), result, colorValue=SIColors.Lavender)
|
|
127
|
+
|
|
128
|
+
# # build member list with friendly names.
|
|
129
|
+
# result:list[str] = []
|
|
130
|
+
# member:GroupInfo = None
|
|
131
|
+
# for key, member in self._CastMultizoneManager._casts.items():
|
|
132
|
+
# group_members:str = member["group_memberships"]
|
|
133
|
+
# if (len(group_members) > 0):
|
|
134
|
+
# result.append(str(member))
|
|
135
|
+
# _logsi.LogArray(SILevel.Verbose, "Chromecast multizone group \"%s\" casts (count=%d)" % (scDevice.Title, len(result)), result, colorValue=SIColors.Lavender)
|
|
136
|
+
|
|
137
|
+
except Exception as ex:
|
|
138
|
+
|
|
139
|
+
# trace.
|
|
140
|
+
_logsi.LogException(SpotifyConnectZeroconfCastMultiZoneManagerListener.UNHANDLED_EXCEPTION_MSG % (apiMethodName), ex, logToSystemLogger=False)
|
|
141
|
+
|
|
142
|
+
# ignore exception, as nothing can be done about it.
|
|
143
|
+
|
|
144
|
+
finally:
|
|
145
|
+
|
|
146
|
+
# trace.
|
|
147
|
+
_logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def removed_from_multizone(
|
|
151
|
+
self,
|
|
152
|
+
group_uuid,
|
|
153
|
+
) -> None:
|
|
154
|
+
"""
|
|
155
|
+
Called when cast has been removed from group identified by group_uuid.
|
|
156
|
+
"""
|
|
157
|
+
# use lock, as multiple threads could be calling this method simultaneously.
|
|
158
|
+
with self._Zeroconf_RLock:
|
|
159
|
+
|
|
160
|
+
# copy passed parameters to thread-safe storage.
|
|
161
|
+
argsGroupUuid:UUID = group_uuid
|
|
162
|
+
|
|
163
|
+
apiMethodName:str = "removed_from_multizone (MultiZoneManagerListener)"
|
|
164
|
+
apiMethodParms:SIMethodParmListContext = None
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
|
|
168
|
+
# trace.
|
|
169
|
+
apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
|
|
170
|
+
apiMethodParms.AppendKeyValue("group_uuid", argsGroupUuid)
|
|
171
|
+
_logsi.LogMethodParmList(SILevel.Debug, "Chromecast multizone manager notification was received for group \"%s\"" % (argsGroupUuid), apiMethodParms, colorValue=SIColors.Lavender)
|
|
172
|
+
|
|
173
|
+
# trace.
|
|
174
|
+
if (_logsi.IsOn(SILevel.Verbose)):
|
|
175
|
+
|
|
176
|
+
# get group device instance.
|
|
177
|
+
scDevice:SpotifyConnectDevice = self._ParentDirectory._SpotifyConnectDevices.GetDeviceByDiscoveryKey(str(argsGroupUuid))
|
|
178
|
+
if (scDevice is None):
|
|
179
|
+
|
|
180
|
+
# trace.
|
|
181
|
+
_logsi.LogVerbose("Could not find SpotifyConnectDevices instance for Cast device key: \"%s\"" % (str(argsGroupUuid)), colorValue=SIColors.Lavender)
|
|
182
|
+
|
|
183
|
+
else:
|
|
184
|
+
|
|
185
|
+
# trace.
|
|
186
|
+
_logsi.LogVerbose("Chromecast multizone manager removed device \"%s\" from multizone group %s" % (self._CastDevice.cast_info.friendly_name, scDevice.Title), colorValue=SIColors.Lavender)
|
|
187
|
+
|
|
188
|
+
# # get the current multizone status.
|
|
189
|
+
# castMultiZoneStatus:MultizoneStatus = get_multizone_status(scDevice.DiscoveryResult.HostIpAddress, self._CastDevice.cast_info.services, self._ZeroconfInstance, 5)
|
|
190
|
+
# _logsi.LogObject(SILevel.Verbose, "Chromecast multizone manager status for group: %s [%s] (get_multizone_status)" % (scDevice.Title, scDevice.DiscoveryResult.HostIpTitle), castMultiZoneStatus, colorValue=SIColors.Lavender)
|
|
191
|
+
|
|
192
|
+
# # build member list with friendly names.
|
|
193
|
+
# result:list[str] = []
|
|
194
|
+
# member:GroupInfo = None
|
|
195
|
+
# for key, member in self._CastMultizoneManager._groups.items():
|
|
196
|
+
# memberName:str = member["chromecast"].cast_info.friendly_name
|
|
197
|
+
# result.append(memberName + ": " + str(member))
|
|
198
|
+
# _logsi.LogArray(SILevel.Verbose, "Chromecast multizone group \"%s\" groups (count=%d)" % (scDevice.Title, len(result)), result, colorValue=SIColors.Lavender)
|
|
199
|
+
|
|
200
|
+
# # build member list with friendly names.
|
|
201
|
+
# result:list[str] = []
|
|
202
|
+
# member:GroupInfo = None
|
|
203
|
+
# for key, member in self._CastMultizoneManager._casts.items():
|
|
204
|
+
# group_members:str = member["group_memberships"]
|
|
205
|
+
# if (len(group_members) > 0):
|
|
206
|
+
# result.append(str(member))
|
|
207
|
+
# _logsi.LogArray(SILevel.Verbose, "Chromecast multizone group \"%s\" casts (count=%d)" % (scDevice.Title, len(result)), result, colorValue=SIColors.Lavender)
|
|
208
|
+
|
|
209
|
+
except Exception as ex:
|
|
210
|
+
|
|
211
|
+
# trace.
|
|
212
|
+
_logsi.LogException(SpotifyConnectZeroconfCastMultiZoneManagerListener.UNHANDLED_EXCEPTION_MSG % (apiMethodName), ex, logToSystemLogger=False)
|
|
213
|
+
|
|
214
|
+
# ignore exception, as nothing can be done about it.
|
|
215
|
+
|
|
216
|
+
finally:
|
|
217
|
+
|
|
218
|
+
# trace.
|
|
219
|
+
_logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def multizone_new_media_status(
|
|
223
|
+
self,
|
|
224
|
+
group_uuid: str,
|
|
225
|
+
media_status: MediaStatus
|
|
226
|
+
) -> None:
|
|
227
|
+
"""
|
|
228
|
+
Called when the group identified by group_uuid, of which the cast is a member, has new media status.
|
|
229
|
+
"""
|
|
230
|
+
|
|
231
|
+
# Commented out this code, as we do not use it.
|
|
232
|
+
# Left it in place, in case it's required in the future.
|
|
233
|
+
pass
|
|
234
|
+
|
|
235
|
+
# # use lock, as multiple threads could be calling this method simultaneously.
|
|
236
|
+
# with self._Zeroconf_RLock:
|
|
237
|
+
|
|
238
|
+
# # copy passed parameters to thread-safe storage.
|
|
239
|
+
# argsGroupUuid:UUID = group_uuid
|
|
240
|
+
# argsMediaStatus:MediaStatus = media_status
|
|
241
|
+
|
|
242
|
+
# apiMethodName:str = "multizone_new_media_status (MultiZoneManagerListener)"
|
|
243
|
+
# apiMethodParms:SIMethodParmListContext = None
|
|
244
|
+
|
|
245
|
+
# try:
|
|
246
|
+
|
|
247
|
+
# # trace.
|
|
248
|
+
# apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
|
|
249
|
+
# apiMethodParms.AppendKeyValue("group_uuid", argsGroupUuid)
|
|
250
|
+
# apiMethodParms.AppendKeyValue("media_status", argsMediaStatus)
|
|
251
|
+
# _logsi.LogMethodParmList(SILevel.Debug, "Chromecast multizone manager media status has been updated for group: \"%s\"" % (argsGroupUuid), apiMethodParms, colorValue=SIColors.Lavender)
|
|
252
|
+
|
|
253
|
+
# # example - MediaStatus:
|
|
254
|
+
# # {
|
|
255
|
+
# # 'metadata_type': 3,
|
|
256
|
+
# # 'title': 'Fire And Ice',
|
|
257
|
+
# # 'series_title': None,
|
|
258
|
+
# # 'season': None,
|
|
259
|
+
# # 'episode': None,
|
|
260
|
+
# # 'artist': 'Steve Camp',
|
|
261
|
+
# # 'album_name': 'Fire And Ice',
|
|
262
|
+
# # 'album_artist': None,
|
|
263
|
+
# # 'track': None,
|
|
264
|
+
# # 'subtitle_tracks': [],
|
|
265
|
+
# # 'images': [MediaImage(url = 'https://i.scdn.co/image/ab67 ...')],
|
|
266
|
+
# # 'content_id': 'spotify:track:4M7fCbUaDpYWNKSEZfLpSb',
|
|
267
|
+
# # 'content_type': 'application/x-spotify.track',
|
|
268
|
+
# # ... <==== truncated for brevity; see developer docs for more details
|
|
269
|
+
# # }
|
|
270
|
+
|
|
271
|
+
# # trace.
|
|
272
|
+
# if (_logsi.IsOn(SILevel.Verbose)):
|
|
273
|
+
|
|
274
|
+
# # get group device instance.
|
|
275
|
+
# scDevice:SpotifyConnectDevice = self._ParentDirectory._SpotifyConnectDevices.GetDeviceByDiscoveryKey(str(argsGroupUuid))
|
|
276
|
+
# if (scDevice is None):
|
|
277
|
+
|
|
278
|
+
# # trace.
|
|
279
|
+
# _logsi.LogVerbose("Could not find SpotifyConnectDevices instance for Cast device key: \"%s\"" % (str(argsGroupUuid)), colorValue=SIColors.Lavender)
|
|
280
|
+
|
|
281
|
+
# else:
|
|
282
|
+
|
|
283
|
+
# # formulate current status.
|
|
284
|
+
# statusText:str = "unknown"
|
|
285
|
+
# if (argsMediaStatus):
|
|
286
|
+
# statusText = "%s (%s)" % (argsMediaStatus.title or "null", argsMediaStatus.artist or "null")
|
|
287
|
+
|
|
288
|
+
# # trace.
|
|
289
|
+
# _logsi.LogObject(SILevel.Verbose, "Chromecast multizone manager group MediaStatus: %s [%s] - %s" % (scDevice.Title, scDevice.DiscoveryResult.HostIpTitle, statusText), argsMediaStatus, colorValue=SIColors.Lavender)
|
|
290
|
+
|
|
291
|
+
# except Exception as ex:
|
|
292
|
+
|
|
293
|
+
# # trace.
|
|
294
|
+
# _logsi.LogException(SpotifyConnectZeroconfCastMultiZoneManagerListener.UNHANDLED_EXCEPTION_MSG % (apiMethodName), ex, logToSystemLogger=False)
|
|
295
|
+
|
|
296
|
+
# # ignore exception, as nothing can be done about it.
|
|
297
|
+
|
|
298
|
+
# finally:
|
|
299
|
+
|
|
300
|
+
# # trace.
|
|
301
|
+
# _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def multizone_new_cast_status(
|
|
305
|
+
self,
|
|
306
|
+
group_uuid: str,
|
|
307
|
+
cast_status: CastStatus
|
|
308
|
+
) -> None:
|
|
309
|
+
"""
|
|
310
|
+
Called when the group identified by group_uuid, of which the cast is a member, has new status.
|
|
311
|
+
"""
|
|
312
|
+
# Commented out this code, as we do not use it.
|
|
313
|
+
# Left it in place, in case it's required in the future.
|
|
314
|
+
#pass
|
|
315
|
+
|
|
316
|
+
# use lock, as multiple threads could be calling this method simultaneously.
|
|
317
|
+
with self._Zeroconf_RLock:
|
|
318
|
+
|
|
319
|
+
# copy passed parameters to thread-safe storage.
|
|
320
|
+
argsGroupUuid:UUID = group_uuid
|
|
321
|
+
argsCastStatus:CastStatus = cast_status
|
|
322
|
+
|
|
323
|
+
apiMethodName:str = "multizone_new_cast_status (MultiZoneManagerListener)"
|
|
324
|
+
apiMethodParms:SIMethodParmListContext = None
|
|
325
|
+
|
|
326
|
+
try:
|
|
327
|
+
|
|
328
|
+
# trace.
|
|
329
|
+
apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
|
|
330
|
+
apiMethodParms.AppendKeyValue("group_uuid", argsGroupUuid)
|
|
331
|
+
apiMethodParms.AppendKeyValue("cast_status", argsCastStatus)
|
|
332
|
+
_logsi.LogMethodParmList(SILevel.Debug, "Chromecast multizone manager cast status has been updated for group: \"%s\"" % (argsGroupUuid), apiMethodParms, colorValue=SIColors.Lavender)
|
|
333
|
+
|
|
334
|
+
# example - CastStatus:
|
|
335
|
+
# {
|
|
336
|
+
# "is_active_input": "None",
|
|
337
|
+
# "is_stand_by": "None",
|
|
338
|
+
# "volume_level": "0.10000763088464737",
|
|
339
|
+
# "volume_muted": "False",
|
|
340
|
+
# "app_id": "CC32E753",
|
|
341
|
+
# "display_name": "Spotify",
|
|
342
|
+
# "namespaces": ['urn:x-cast:com.google.cast.debugoverlay',
|
|
343
|
+
# 'urn:x-cast:com.google.cast.cac',
|
|
344
|
+
# 'urn:x-cast:com.spotify.chromecast.secure.v1',
|
|
345
|
+
# 'urn:x-cast:com.google.cast.media'
|
|
346
|
+
# ],
|
|
347
|
+
# "session_id": "690a6e31-647d-4808-97f1-cc65cf2eb473",
|
|
348
|
+
# "transport_id": "690a6e31-647d-4808-97f1-cc65cf2eb473",
|
|
349
|
+
# "status_text": "Casting: Strong Enough",
|
|
350
|
+
# "icon_url": "https://lh3.googleusercontent.com/oodettwQnQA4LTRxkeyqf93S8J6gbWu9r8DPsiVsDoiTffNV2xhiSeNnFCQ8zh5I4xGaAH_xyLzLx3E6",
|
|
351
|
+
# "volume_control_type": "master"
|
|
352
|
+
# }
|
|
353
|
+
|
|
354
|
+
# trace.
|
|
355
|
+
if (_logsi.IsOn(SILevel.Verbose)):
|
|
356
|
+
|
|
357
|
+
# get group device instance.
|
|
358
|
+
scDevice:SpotifyConnectDevice = self._ParentDirectory._SpotifyConnectDevices.GetDeviceByDiscoveryKey(str(argsGroupUuid))
|
|
359
|
+
if (scDevice is None):
|
|
360
|
+
|
|
361
|
+
# trace.
|
|
362
|
+
_logsi.LogVerbose("Could not find SpotifyConnectDevices instance for Cast device key: \"%s\"" % (str(argsGroupUuid)), colorValue=SIColors.Lavender)
|
|
363
|
+
|
|
364
|
+
else:
|
|
365
|
+
|
|
366
|
+
# formulate current status.
|
|
367
|
+
statusText:str = "unknown"
|
|
368
|
+
if (argsCastStatus):
|
|
369
|
+
statusText = "%s: %s" % (argsCastStatus.display_name or "null", argsCastStatus.status_text or "null")
|
|
370
|
+
|
|
371
|
+
# trace.
|
|
372
|
+
_logsi.LogObject(SILevel.Verbose, "Chromecast multizone manager group CastStatus: %s [%s] - %s" % (scDevice.Title, scDevice.DiscoveryResult.HostIpTitle, statusText), argsCastStatus, colorValue=SIColors.Lavender)
|
|
373
|
+
|
|
374
|
+
except Exception as ex:
|
|
375
|
+
|
|
376
|
+
# trace.
|
|
377
|
+
_logsi.LogException(SpotifyConnectZeroconfCastMultiZoneManagerListener.UNHANDLED_EXCEPTION_MSG % (apiMethodName), ex, logToSystemLogger=False)
|
|
378
|
+
|
|
379
|
+
# ignore exception, as nothing can be done about it.
|
|
380
|
+
|
|
381
|
+
finally:
|
|
382
|
+
|
|
383
|
+
# trace.
|
|
384
|
+
_logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|