spotifywebapiPython 1.0.242__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/__init__.py +35 -0
- spotifywebapipython/const.py +114 -0
- spotifywebapipython/docs/__init__.html +2156 -0
- spotifywebapipython/docs/codecopy.js +70 -0
- spotifywebapipython/docs/index.html +514 -0
- spotifywebapipython/docs/search.js +46 -0
- spotifywebapipython/docs/spotifywebapipython/const.html +636 -0
- spotifywebapipython/docs/spotifywebapipython/saappmessages.html +540 -0
- spotifywebapipython/docs/spotifywebapipython/sautils.html +620 -0
- spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html +341 -0
- spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html +598 -0
- spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html +612 -0
- spotifywebapipython/docs/spotifywebapipython/spotifyclient.html +16557 -0
- spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html +518 -0
- spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html +421 -0
- spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html +400 -0
- spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html +635 -0
- spotifywebapipython/docs/spotifywebapipython.ico +0 -0
- spotifywebapipython/docs/spotifywebapipython_OLD.ico +0 -0
- spotifywebapipython/models/__init__.py +121 -0
- spotifywebapipython/models/album.py +170 -0
- spotifywebapipython/models/albumpagesaved.py +85 -0
- spotifywebapipython/models/albumpagesimplified.py +88 -0
- spotifywebapipython/models/albumsaved.py +102 -0
- spotifywebapipython/models/albumsimplified.py +308 -0
- spotifywebapipython/models/artist.py +146 -0
- spotifywebapipython/models/artistinfo.py +282 -0
- spotifywebapipython/models/artistinfotourevent.py +127 -0
- spotifywebapipython/models/artistpage.py +70 -0
- spotifywebapipython/models/artistsimplified.py +163 -0
- spotifywebapipython/models/audiobook.py +87 -0
- spotifywebapipython/models/audiobookpagesimplified.py +88 -0
- spotifywebapipython/models/audiobooksimplified.py +362 -0
- spotifywebapipython/models/audiofeatures.py +333 -0
- spotifywebapipython/models/author.py +67 -0
- spotifywebapipython/models/category.py +168 -0
- spotifywebapipython/models/categorypage.py +70 -0
- spotifywebapipython/models/chapter.py +84 -0
- spotifywebapipython/models/chapterpagesimplified.py +88 -0
- spotifywebapipython/models/chaptersimplified.py +387 -0
- spotifywebapipython/models/context.py +113 -0
- spotifywebapipython/models/copyright.py +79 -0
- spotifywebapipython/models/device.py +301 -0
- spotifywebapipython/models/episode.py +84 -0
- spotifywebapipython/models/episodepagesaved.py +85 -0
- spotifywebapipython/models/episodepagesimplified.py +88 -0
- spotifywebapipython/models/episodesaved.py +99 -0
- spotifywebapipython/models/episodesimplified.py +370 -0
- spotifywebapipython/models/explicitcontent.py +80 -0
- spotifywebapipython/models/externalids.py +91 -0
- spotifywebapipython/models/externalurls.py +104 -0
- spotifywebapipython/models/followers.py +81 -0
- spotifywebapipython/models/imageobject.py +193 -0
- spotifywebapipython/models/imagevibrantcolors.py +182 -0
- spotifywebapipython/models/linkedfrom.py +165 -0
- spotifywebapipython/models/narrator.py +67 -0
- spotifywebapipython/models/owner.py +162 -0
- spotifywebapipython/models/pageobject.py +343 -0
- spotifywebapipython/models/playeractions.py +196 -0
- spotifywebapipython/models/playerlastplayedinfo.py +334 -0
- spotifywebapipython/models/playerplaystate.py +467 -0
- spotifywebapipython/models/playerqueueinfo.py +207 -0
- spotifywebapipython/models/playhistory.py +136 -0
- spotifywebapipython/models/playhistorypage.py +85 -0
- spotifywebapipython/models/playlist.py +125 -0
- spotifywebapipython/models/playlistpage.py +85 -0
- spotifywebapipython/models/playlistpagesimplified.py +107 -0
- spotifywebapipython/models/playlistsimplified.py +334 -0
- spotifywebapipython/models/playlisttrack.py +143 -0
- spotifywebapipython/models/playlisttracksummary.py +80 -0
- spotifywebapipython/models/recommendationseed.py +135 -0
- spotifywebapipython/models/restrictions.py +86 -0
- spotifywebapipython/models/resumepoint.py +79 -0
- spotifywebapipython/models/searchresponse.py +391 -0
- spotifywebapipython/models/searchresultbase.py +299 -0
- spotifywebapipython/models/show.py +87 -0
- spotifywebapipython/models/showpagesaved.py +85 -0
- spotifywebapipython/models/showpagesimplified.py +88 -0
- spotifywebapipython/models/showsaved.py +99 -0
- spotifywebapipython/models/showsimplified.py +320 -0
- spotifywebapipython/models/spotifyconnectdevice.py +321 -0
- spotifywebapipython/models/spotifyconnectdevices.py +441 -0
- spotifywebapipython/models/track.py +142 -0
- spotifywebapipython/models/trackpage.py +110 -0
- spotifywebapipython/models/trackpagesaved.py +85 -0
- spotifywebapipython/models/trackpagesimplified.py +88 -0
- spotifywebapipython/models/trackrecommendations.py +88 -0
- spotifywebapipython/models/tracksaved.py +99 -0
- spotifywebapipython/models/tracksimplified.py +398 -0
- spotifywebapipython/models/userprofile.py +184 -0
- spotifywebapipython/models/userprofilesimplified.py +206 -0
- spotifywebapipython/models/zeroconfdiscoveryresult.py +592 -0
- spotifywebapipython/models/zeroconfproperty.py +93 -0
- spotifywebapipython/oauthcli/__init__.py +7 -0
- spotifywebapipython/oauthcli/authclient.py +1229 -0
- spotifywebapipython/saappmessages.py +86 -0
- spotifywebapipython/sautils.py +285 -0
- spotifywebapipython/spotifyapierror.py +66 -0
- spotifywebapipython/spotifyapimessage.py +269 -0
- spotifywebapipython/spotifyauthtoken.py +264 -0
- spotifywebapipython/spotifyclient.py +17885 -0
- spotifywebapipython/spotifyconnect/__init__.py +19 -0
- spotifywebapipython/spotifyconnect/spotifyconnectdeviceeventargs.py +67 -0
- spotifywebapipython/spotifyconnect/spotifyconnectdirectorytask.py +2564 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastapptask.py +467 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastcontroller.py +701 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastlistener.py +359 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonelistener.py +212 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfexceptions.py +20 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconflistener.py +335 -0
- spotifywebapipython/spotifydiscovery.py +473 -0
- spotifywebapipython/spotifymediatypes.py +53 -0
- spotifywebapipython/spotifywebapiauthenticationerror.py +122 -0
- spotifywebapipython/spotifywebapierror.py +106 -0
- spotifywebapipython/spotifywebplayertoken.py +743 -0
- spotifywebapipython/vibrant/__init__.py +17 -0
- spotifywebapipython/vibrant/generator.py +261 -0
- spotifywebapipython/vibrant/image.py +100 -0
- spotifywebapipython/vibrant/main.py +34 -0
- spotifywebapipython/vibrant/models.py +93 -0
- spotifywebapipython/vibrant/utils.py +56 -0
- spotifywebapipython/zeroconfapi/__init__.py +23 -0
- spotifywebapipython/zeroconfapi/authenticationtypes.py +38 -0
- spotifywebapipython/zeroconfapi/blobbuilder.py +370 -0
- spotifywebapipython/zeroconfapi/credentials.py +37 -0
- spotifywebapipython/zeroconfapi/cryptodiffiehellman.py +89 -0
- spotifywebapipython/zeroconfapi/helpers.py +64 -0
- spotifywebapipython/zeroconfapi/spotifyzeroconfapierror.py +108 -0
- spotifywebapipython/zeroconfapi/zeroconfconnect.py +1327 -0
- spotifywebapipython/zeroconfapi/zeroconfgetinfo.py +572 -0
- spotifywebapipython/zeroconfapi/zeroconfgetinfoalias.py +109 -0
- spotifywebapipython/zeroconfapi/zeroconfgetinfodrmmediaformat.py +90 -0
- spotifywebapipython/zeroconfapi/zeroconfresponse.py +195 -0
- spotifywebapipython-1.0.242.dist-info/LICENSE +22 -0
- spotifywebapipython-1.0.242.dist-info/METADATA +219 -0
- spotifywebapipython-1.0.242.dist-info/RECORD +138 -0
- spotifywebapipython-1.0.242.dist-info/WHEEL +5 -0
- spotifywebapipython-1.0.242.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
# external package imports.
|
|
2
|
+
|
|
3
|
+
# our package imports.
|
|
4
|
+
from ..sautils import export
|
|
5
|
+
from ..spotifymediatypes import SpotifyMediaTypes
|
|
6
|
+
from .context import Context
|
|
7
|
+
from .device import Device
|
|
8
|
+
from .episode import Episode
|
|
9
|
+
from .playeractions import PlayerActions
|
|
10
|
+
from .track import Track
|
|
11
|
+
|
|
12
|
+
@export
|
|
13
|
+
class PlayerPlayState:
|
|
14
|
+
"""
|
|
15
|
+
Spotify Web API PlayerPlayState object.
|
|
16
|
+
|
|
17
|
+
Information about the user's current playback state, including track or episode,
|
|
18
|
+
progress, and active device.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, root:dict=None) -> None:
|
|
22
|
+
"""
|
|
23
|
+
Initializes a new instance of the class.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
root (dict):
|
|
27
|
+
Spotify Web API JSON response in dictionary format, used to load object
|
|
28
|
+
attributes; otherwise, None to not load attributes.
|
|
29
|
+
"""
|
|
30
|
+
self._Actions:PlayerActions = None
|
|
31
|
+
self._Context:Context = None
|
|
32
|
+
self._ItemType:str = None
|
|
33
|
+
self._CurrentlyPlayingType:str = None
|
|
34
|
+
self._Device:Device = None
|
|
35
|
+
self._DeviceMusicSource:str = None
|
|
36
|
+
self._Item:object = None
|
|
37
|
+
self._IsDeviceState:bool = False
|
|
38
|
+
self._IsPlaying:bool = None
|
|
39
|
+
self._ProgressMS:int = None
|
|
40
|
+
self._RepeatState:str = None
|
|
41
|
+
self._ShuffleState:bool = None
|
|
42
|
+
self._SmartShuffle:bool = None
|
|
43
|
+
self._Timestamp:int = None
|
|
44
|
+
|
|
45
|
+
# helper properties, not part of the Spotify Web API interface.
|
|
46
|
+
self._IsEmpty:bool = True
|
|
47
|
+
|
|
48
|
+
if (root is None):
|
|
49
|
+
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
else:
|
|
53
|
+
|
|
54
|
+
self._CurrentlyPlayingType = root.get('currently_playing_type', None)
|
|
55
|
+
self._IsPlaying = root.get('is_playing', None)
|
|
56
|
+
self._ProgressMS = root.get('progress_ms', None)
|
|
57
|
+
self._RepeatState = root.get('repeat_state', None)
|
|
58
|
+
self._ShuffleState = root.get('shuffle_state', None)
|
|
59
|
+
self._SmartShuffle = root.get('smart_shuffle', None)
|
|
60
|
+
self._Timestamp = root.get('timestamp', None)
|
|
61
|
+
|
|
62
|
+
# process all collections and objects.
|
|
63
|
+
item:dict = root.get('actions',None)
|
|
64
|
+
if item is not None:
|
|
65
|
+
disallows:dict = item.get('disallows')
|
|
66
|
+
if disallows is not None:
|
|
67
|
+
self._Actions = PlayerActions(root=disallows)
|
|
68
|
+
|
|
69
|
+
item:dict = root.get('context',None)
|
|
70
|
+
if item is not None:
|
|
71
|
+
self._Context = Context(root=item)
|
|
72
|
+
|
|
73
|
+
item:dict = root.get('device',None)
|
|
74
|
+
if item is not None:
|
|
75
|
+
self._Device = Device(root=item)
|
|
76
|
+
|
|
77
|
+
item:dict = root.get('item',None)
|
|
78
|
+
if item is not None:
|
|
79
|
+
if self._CurrentlyPlayingType == SpotifyMediaTypes.TRACK.value:
|
|
80
|
+
self._Item = Track(root=item)
|
|
81
|
+
elif self._CurrentlyPlayingType == SpotifyMediaTypes.EPISODE.value:
|
|
82
|
+
self._Item = Episode(root=item)
|
|
83
|
+
|
|
84
|
+
# if root contains keys, then assume it is NOT empty.
|
|
85
|
+
if (len(root) > 0):
|
|
86
|
+
self._IsEmpty = False
|
|
87
|
+
|
|
88
|
+
# post load validations.
|
|
89
|
+
if self._Actions is None:
|
|
90
|
+
self._Actions = PlayerActions()
|
|
91
|
+
if self._Device is None:
|
|
92
|
+
self._Device = Device()
|
|
93
|
+
if self._CurrentlyPlayingType is None:
|
|
94
|
+
self._CurrentlyPlayingType = 'unknown'
|
|
95
|
+
if self._IsPlaying is None:
|
|
96
|
+
self._IsPlaying = False
|
|
97
|
+
if self._ProgressMS is None:
|
|
98
|
+
self._ProgressMS = 0
|
|
99
|
+
if self._RepeatState is None:
|
|
100
|
+
self._RepeatState = 'off'
|
|
101
|
+
if self._ShuffleState is None:
|
|
102
|
+
self._ShuffleState = False
|
|
103
|
+
if self._SmartShuffle is None:
|
|
104
|
+
self._SmartShuffle = False
|
|
105
|
+
if self._Timestamp is None:
|
|
106
|
+
self._Timestamp = 0
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def __repr__(self) -> str:
|
|
110
|
+
return self.ToString()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def __str__(self) -> str:
|
|
114
|
+
return self.ToString()
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def Actions(self) -> PlayerActions:
|
|
119
|
+
"""
|
|
120
|
+
Allows to update the user interface based on which playback actions are
|
|
121
|
+
available within the current context.
|
|
122
|
+
"""
|
|
123
|
+
return self._Actions
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def Context(self) -> Context:
|
|
128
|
+
"""
|
|
129
|
+
A Context Object; can be null.
|
|
130
|
+
"""
|
|
131
|
+
return self._Context
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def CurrentlyPlayingType(self) -> str:
|
|
136
|
+
"""
|
|
137
|
+
The object type of the currently playing item, or null if nothing is playing.
|
|
138
|
+
|
|
139
|
+
If not null, it can be one of `track`, `episode`, `ad` or `unknown`.
|
|
140
|
+
"""
|
|
141
|
+
return self._CurrentlyPlayingType
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def Device(self) -> Device:
|
|
146
|
+
"""
|
|
147
|
+
The device that is currently active.
|
|
148
|
+
"""
|
|
149
|
+
return self._Device
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def DeviceMusicSource(self) -> str:
|
|
154
|
+
"""
|
|
155
|
+
The device music source.
|
|
156
|
+
This value is device manufacturer specific.
|
|
157
|
+
For example, a Sonos source will contain values like "UNKNOWN", "SPOTIFY_CONNECT", etc.
|
|
158
|
+
|
|
159
|
+
This is a helper property, and is not part of the Spotify Web API specification.
|
|
160
|
+
"""
|
|
161
|
+
return self._DeviceMusicSource
|
|
162
|
+
|
|
163
|
+
@DeviceMusicSource.setter
|
|
164
|
+
def DeviceMusicSource(self, value:str):
|
|
165
|
+
"""
|
|
166
|
+
Sets the DeviceMusicSource property value.
|
|
167
|
+
"""
|
|
168
|
+
self._DeviceMusicSource = value
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def IsAdvertisement(self) -> bool:
|
|
173
|
+
"""
|
|
174
|
+
True if the currently playing media is an advertisement; otherwise, false.
|
|
175
|
+
"""
|
|
176
|
+
if self._CurrentlyPlayingType == "ad":
|
|
177
|
+
return True
|
|
178
|
+
return False
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def IsDeviceState(self) -> bool:
|
|
183
|
+
"""
|
|
184
|
+
True if playstate was built from a device playstate;
|
|
185
|
+
otherwise, false if playstate was built from a Spotify Web API playstate.
|
|
186
|
+
"""
|
|
187
|
+
return self._IsDeviceState
|
|
188
|
+
|
|
189
|
+
@IsDeviceState.setter
|
|
190
|
+
def IsDeviceState(self, value:bool):
|
|
191
|
+
"""
|
|
192
|
+
Sets the IsDeviceState property value.
|
|
193
|
+
"""
|
|
194
|
+
if isinstance(value, bool):
|
|
195
|
+
self._IsDeviceState = value
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def IsEmpty(self) -> bool:
|
|
200
|
+
"""
|
|
201
|
+
True if Spotify playstate returned an empty response; otherwise, false.
|
|
202
|
+
|
|
203
|
+
Note that for Sonos devices, the Spotify Web API reports an empty playstate since
|
|
204
|
+
the SoCo API is actually controlling player.
|
|
205
|
+
|
|
206
|
+
This is a helper property, and is not part of the Spotify Web API specification.
|
|
207
|
+
"""
|
|
208
|
+
return self._IsEmpty
|
|
209
|
+
|
|
210
|
+
@IsEmpty.setter
|
|
211
|
+
def IsEmpty(self, value:bool):
|
|
212
|
+
"""
|
|
213
|
+
Sets the IsEmpty property value.
|
|
214
|
+
"""
|
|
215
|
+
if isinstance(value, bool):
|
|
216
|
+
self._IsEmpty = value
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def IsMuted(self) -> bool:
|
|
221
|
+
"""
|
|
222
|
+
True if the player device volume is zero (muted) OR there is no device;
|
|
223
|
+
otherwise, false.
|
|
224
|
+
"""
|
|
225
|
+
if self._Device is None:
|
|
226
|
+
return True
|
|
227
|
+
else:
|
|
228
|
+
return self._Device.IsMuted
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@property
|
|
232
|
+
def IsPlaying(self) -> bool:
|
|
233
|
+
"""
|
|
234
|
+
True if something is currently playing; otherwise, false.
|
|
235
|
+
"""
|
|
236
|
+
return self._IsPlaying
|
|
237
|
+
|
|
238
|
+
@IsPlaying.setter
|
|
239
|
+
def IsPlaying(self, value:bool):
|
|
240
|
+
"""
|
|
241
|
+
Sets the IsPlaying property value.
|
|
242
|
+
"""
|
|
243
|
+
if isinstance(value, bool):
|
|
244
|
+
self._IsPlaying = value
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
@property
|
|
248
|
+
def IsRepeatEnabled(self) -> bool:
|
|
249
|
+
"""
|
|
250
|
+
True if repeat play (one or all) is enabled; otherwise, False.
|
|
251
|
+
|
|
252
|
+
The `RepeatState` property contains the actual repeat setting.
|
|
253
|
+
"""
|
|
254
|
+
if self._RepeatState != 'off':
|
|
255
|
+
return True
|
|
256
|
+
return False
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
@property
|
|
260
|
+
def IsShuffleEnabled(self) -> bool:
|
|
261
|
+
"""
|
|
262
|
+
True if shuffle play is enabled; otherwise, False.
|
|
263
|
+
"""
|
|
264
|
+
if (self.ShuffleState == 'on') or (self.ShuffleState == True):
|
|
265
|
+
return True
|
|
266
|
+
return False
|
|
267
|
+
|
|
268
|
+
@IsShuffleEnabled.setter
|
|
269
|
+
def IsShuffleEnabled(self, value:bool):
|
|
270
|
+
"""
|
|
271
|
+
Sets the IsShuffleEnabled property value.
|
|
272
|
+
"""
|
|
273
|
+
if isinstance(value, bool):
|
|
274
|
+
self._ShuffleState = value
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
@property
|
|
278
|
+
def IsSmartShuffleEnabled(self) -> bool:
|
|
279
|
+
"""
|
|
280
|
+
True if smart shuffle play is enabled; otherwise, False.
|
|
281
|
+
"""
|
|
282
|
+
if (self.SmartShuffle == 'on' or self.SmartShuffle == True):
|
|
283
|
+
return True
|
|
284
|
+
return False
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@property
|
|
288
|
+
def Item(self) -> object:
|
|
289
|
+
"""
|
|
290
|
+
The currently playing track or episode; can be null.
|
|
291
|
+
|
|
292
|
+
Will be of type `Track`, `Episode`, or null.
|
|
293
|
+
"""
|
|
294
|
+
return self._Item
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
@property
|
|
298
|
+
def ItemType(self) -> str:
|
|
299
|
+
"""
|
|
300
|
+
The type of the currently playing episode; can be null.
|
|
301
|
+
This value will be null if the `Item` property value is null.
|
|
302
|
+
|
|
303
|
+
If not null, it can be one of `audiobook` or `podcast`.
|
|
304
|
+
|
|
305
|
+
Note that this is not a Spotify Web API property; it is loaded from our API so
|
|
306
|
+
that the type of episode can be determined programatically (e.g. audiobook or podcast).
|
|
307
|
+
"""
|
|
308
|
+
return self._ItemType
|
|
309
|
+
|
|
310
|
+
@ItemType.setter
|
|
311
|
+
def ItemType(self, value:str):
|
|
312
|
+
"""
|
|
313
|
+
Sets the ItemType property value.
|
|
314
|
+
"""
|
|
315
|
+
self._ItemType = value
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
@property
|
|
319
|
+
def ProgressMS(self) -> int:
|
|
320
|
+
"""
|
|
321
|
+
Progress into the currently playing track or episode; can be null.
|
|
322
|
+
"""
|
|
323
|
+
return self._ProgressMS
|
|
324
|
+
|
|
325
|
+
@ProgressMS.setter
|
|
326
|
+
def ProgressMS(self, value:int):
|
|
327
|
+
"""
|
|
328
|
+
Sets the ProgressMS property value.
|
|
329
|
+
"""
|
|
330
|
+
if isinstance(value, int):
|
|
331
|
+
self._ProgressMS = value
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
@property
|
|
335
|
+
def RepeatState(self) -> str:
|
|
336
|
+
"""
|
|
337
|
+
The repeat state of the playing track: `off`, `track`, or `context`.
|
|
338
|
+
"""
|
|
339
|
+
return self._RepeatState
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
@property
|
|
343
|
+
def ShuffleState(self) -> bool:
|
|
344
|
+
"""
|
|
345
|
+
If shuffle is enabled, True or False.
|
|
346
|
+
"""
|
|
347
|
+
return self._ShuffleState
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@property
|
|
351
|
+
def SmartShuffle(self) -> bool:
|
|
352
|
+
"""
|
|
353
|
+
If smart shuffle is enabled, True or False.
|
|
354
|
+
"""
|
|
355
|
+
return self._SmartShuffle
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
@property
|
|
359
|
+
def Summary(self) -> str:
|
|
360
|
+
"""
|
|
361
|
+
Returns a summary of what is playing.
|
|
362
|
+
"""
|
|
363
|
+
result:str = ''
|
|
364
|
+
if self._Item is not None:
|
|
365
|
+
|
|
366
|
+
if self._CurrentlyPlayingType == SpotifyMediaTypes.TRACK.value:
|
|
367
|
+
track:Track = self._Item
|
|
368
|
+
result = 'Track "%s" (%s)' % (track.Name, track.Id)
|
|
369
|
+
elif self._CurrentlyPlayingType == SpotifyMediaTypes.EPISODE.value:
|
|
370
|
+
episode:Episode = self._Item
|
|
371
|
+
result = 'Episode "%s" (%s)' % (episode.Name, episode.Id)
|
|
372
|
+
elif self._CurrentlyPlayingType == 'ad':
|
|
373
|
+
result = 'Advertisement'
|
|
374
|
+
|
|
375
|
+
elif self._CurrentlyPlayingType is None and self._Context is None:
|
|
376
|
+
|
|
377
|
+
result = "unavailable"
|
|
378
|
+
|
|
379
|
+
return result
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
@property
|
|
383
|
+
def Timestamp(self) -> int:
|
|
384
|
+
"""
|
|
385
|
+
Unix Millisecond Timestamp when data was fetched.
|
|
386
|
+
"""
|
|
387
|
+
return self._Timestamp
|
|
388
|
+
|
|
389
|
+
@Timestamp.setter
|
|
390
|
+
def Timestamp(self, value:int):
|
|
391
|
+
"""
|
|
392
|
+
Sets the Timestamp property value.
|
|
393
|
+
"""
|
|
394
|
+
if isinstance(value, int):
|
|
395
|
+
self._Timestamp = value
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def ToDictionary(self) -> dict:
|
|
399
|
+
"""
|
|
400
|
+
Returns a dictionary representation of the class.
|
|
401
|
+
"""
|
|
402
|
+
actions:dict = {}
|
|
403
|
+
if self._Actions is not None:
|
|
404
|
+
actions = self._Actions.ToDictionary()
|
|
405
|
+
|
|
406
|
+
context:dict = {}
|
|
407
|
+
if self._Context is not None:
|
|
408
|
+
context = self._Context.ToDictionary()
|
|
409
|
+
|
|
410
|
+
device:dict = {}
|
|
411
|
+
if self._Device is not None:
|
|
412
|
+
device = self._Device.ToDictionary()
|
|
413
|
+
|
|
414
|
+
item:dict = {}
|
|
415
|
+
if self._Item is not None:
|
|
416
|
+
item = self._Item.ToDictionary()
|
|
417
|
+
|
|
418
|
+
result:dict = \
|
|
419
|
+
{
|
|
420
|
+
'is_empty': self._IsEmpty,
|
|
421
|
+
'actions': actions,
|
|
422
|
+
'context': context,
|
|
423
|
+
'currently_playing_type': self._CurrentlyPlayingType,
|
|
424
|
+
'device': device,
|
|
425
|
+
'device_music_source': self._DeviceMusicSource,
|
|
426
|
+
'is_advertisement': self.IsAdvertisement,
|
|
427
|
+
'is_device_state': self.IsDeviceState,
|
|
428
|
+
'is_muted': self.IsMuted,
|
|
429
|
+
'is_playing': self._IsPlaying,
|
|
430
|
+
'is_repeat_enabled': self.IsRepeatEnabled,
|
|
431
|
+
'is_shuffle_enabled': self.IsShuffleEnabled,
|
|
432
|
+
'progress_ms': self._ProgressMS,
|
|
433
|
+
'repeat_state': self._RepeatState,
|
|
434
|
+
'shuffle_state': self._ShuffleState,
|
|
435
|
+
'smart_shuffle': self._SmartShuffle,
|
|
436
|
+
'timestamp': self._Timestamp,
|
|
437
|
+
'item_type': self._ItemType,
|
|
438
|
+
'item': item,
|
|
439
|
+
}
|
|
440
|
+
return result
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
def ToString(self) -> str:
|
|
444
|
+
"""
|
|
445
|
+
Returns a displayable string representation of the class.
|
|
446
|
+
"""
|
|
447
|
+
msg:str = 'PlayerPlayState:'
|
|
448
|
+
#if self._Actions is not None: msg = '%s\n %s' % (msg, str(self._Actions))
|
|
449
|
+
if self._CurrentlyPlayingType is not None: msg = '%s\n CurrentlyPlayingType="%s"' % (msg, str(self._CurrentlyPlayingType))
|
|
450
|
+
if self._ItemType is not None: msg = '%s\n ItemType="%s"' % (msg, str(self._ItemType))
|
|
451
|
+
if self._Device is not None: msg = '%s\n Device Name="%s"' % (msg, str(self._Device.Name))
|
|
452
|
+
if self._DeviceMusicSource is not None: msg = '%s\n DeviceMusicSource="%s"' % (msg, str(self._DeviceMusicSource))
|
|
453
|
+
#if self._Context is not None: msg = '%s\n %s' % (msg, str(self._Context))
|
|
454
|
+
#if self._Item is not None: msg = '%s\n %s' % (msg, str(self._Item))
|
|
455
|
+
msg = '%s\n IsEmpty="%s"' % (msg, str(self.IsEmpty))
|
|
456
|
+
msg = '%s\n IsAdvertisement="%s"' % (msg, str(self.IsAdvertisement))
|
|
457
|
+
msg = '%s\n IsDeviceState="%s"' % (msg, str(self.IsDeviceState))
|
|
458
|
+
msg = '%s\n IsMuted="%s"' % (msg, str(self.IsMuted))
|
|
459
|
+
msg = '%s\n IsPlaying="%s"' % (msg, str(self.IsPlaying))
|
|
460
|
+
msg = '%s\n IsRepeatEnabled="%s"' % (msg, str(self.IsRepeatEnabled))
|
|
461
|
+
msg = '%s\n IsShuffleEnabled="%s"' % (msg, str(self.IsShuffleEnabled))
|
|
462
|
+
if self._ProgressMS is not None: msg = '%s\n ProgressMS="%s"' % (msg, str(self._ProgressMS))
|
|
463
|
+
if self._RepeatState is not None: msg = '%s\n RepeatState="%s"' % (msg, str(self._RepeatState))
|
|
464
|
+
if self._ShuffleState is not None: msg = '%s\n ShuffleState="%s"' % (msg, str(self._ShuffleState))
|
|
465
|
+
if self._SmartShuffle is not None: msg = '%s\n SmartShuffle="%s"' % (msg, str(self._SmartShuffle))
|
|
466
|
+
if self._Timestamp is not None: msg = '%s\n Timestamp="%s"' % (msg, str(self._Timestamp))
|
|
467
|
+
return msg
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# external package imports.
|
|
2
|
+
|
|
3
|
+
# our package imports.
|
|
4
|
+
from ..sautils import export
|
|
5
|
+
from ..spotifymediatypes import SpotifyMediaTypes
|
|
6
|
+
from .episode import Episode
|
|
7
|
+
from .track import Track
|
|
8
|
+
|
|
9
|
+
@export
|
|
10
|
+
class PlayerQueueInfo:
|
|
11
|
+
"""
|
|
12
|
+
Spotify Web API PlayerQueueInfo object.
|
|
13
|
+
|
|
14
|
+
Information about the user's current playback queue.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, root:dict=None) -> None:
|
|
18
|
+
"""
|
|
19
|
+
Initializes a new instance of the class.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
root (dict):
|
|
23
|
+
Spotify Web API JSON response in dictionary format, used to load object
|
|
24
|
+
attributes; otherwise, None to not load attributes.
|
|
25
|
+
"""
|
|
26
|
+
self._CurrentlyPlaying:object = None
|
|
27
|
+
self._CurrentlyPlayingType:str = None
|
|
28
|
+
self._DateLastRefreshed:float = 0
|
|
29
|
+
self._Queue:list[object] = []
|
|
30
|
+
|
|
31
|
+
if (root is None):
|
|
32
|
+
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
else:
|
|
36
|
+
|
|
37
|
+
# process all collections and objects.
|
|
38
|
+
item:dict = root.get('currently_playing',None)
|
|
39
|
+
if item is not None:
|
|
40
|
+
|
|
41
|
+
self._CurrentlyPlayingType = item.get('type','unknown')
|
|
42
|
+
if self._CurrentlyPlayingType == SpotifyMediaTypes.TRACK.value:
|
|
43
|
+
self._CurrentlyPlaying = Track(root=item)
|
|
44
|
+
elif self._CurrentlyPlayingType == SpotifyMediaTypes.EPISODE.value:
|
|
45
|
+
self._CurrentlyPlaying = Episode(root=item)
|
|
46
|
+
|
|
47
|
+
# for some reason, the Spotify Web API will return up to 10 duplicate items
|
|
48
|
+
# with the same information! for example:
|
|
49
|
+
# - if there is only 1 item in the queue, then 10 duplicate items are returned by the Spotify Web API.
|
|
50
|
+
# - if there are 5 items in the queue, then 5 duplicate items are returned by the Spotify Web API.
|
|
51
|
+
# we will check for this scenario, and only return non-duplicate items if so.
|
|
52
|
+
items:list = root.get('queue',None)
|
|
53
|
+
if items is not None:
|
|
54
|
+
for item in items:
|
|
55
|
+
|
|
56
|
+
itemType = item.get('type','unknown')
|
|
57
|
+
if itemType == SpotifyMediaTypes.TRACK.value:
|
|
58
|
+
track:Track = Track(root=item)
|
|
59
|
+
if (track) and (not self.ContainsUri(track.Uri)):
|
|
60
|
+
self._Queue.append(track)
|
|
61
|
+
elif itemType == SpotifyMediaTypes.EPISODE.value:
|
|
62
|
+
episode:Episode = Episode(root=item)
|
|
63
|
+
if (episode) and (not self.ContainsUri(episode.Uri)):
|
|
64
|
+
self._Queue.append(episode)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def __repr__(self) -> str:
|
|
68
|
+
return self.ToString()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def __str__(self) -> str:
|
|
72
|
+
return self.ToString()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def CurrentlyPlaying(self) -> object:
|
|
77
|
+
"""
|
|
78
|
+
The currently playing track or episode; can be null.
|
|
79
|
+
"""
|
|
80
|
+
return self._CurrentlyPlaying
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def CurrentlyPlayingType(self) -> str:
|
|
85
|
+
"""
|
|
86
|
+
The object type of the currently playing item, or null if nothing is playing.
|
|
87
|
+
|
|
88
|
+
If not null, it can be one of `track`, `episode`, `ad` or `unknown`.
|
|
89
|
+
"""
|
|
90
|
+
return self._CurrentlyPlayingType
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def DateLastRefreshed(self) -> float:
|
|
95
|
+
"""
|
|
96
|
+
Date and time items were was last refreshed, in unix epoch format (e.g. 1669123919.331225).
|
|
97
|
+
A value of zero indicates the date was unknown.
|
|
98
|
+
|
|
99
|
+
Note that this attribute does not exist in the Spotify Web API;
|
|
100
|
+
it was added here for convenience.
|
|
101
|
+
"""
|
|
102
|
+
return self._DateLastRefreshed
|
|
103
|
+
|
|
104
|
+
@DateLastRefreshed.setter
|
|
105
|
+
def DateLastRefreshed(self, value:float):
|
|
106
|
+
"""
|
|
107
|
+
Sets the DateLastRefreshed property value.
|
|
108
|
+
"""
|
|
109
|
+
if (value is None):
|
|
110
|
+
self._DateLastRefreshed = 0
|
|
111
|
+
elif isinstance(value, float):
|
|
112
|
+
self._DateLastRefreshed = value
|
|
113
|
+
elif isinstance(value, int):
|
|
114
|
+
self._DateLastRefreshed = float(value)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def Queue(self) -> list[object]:
|
|
119
|
+
"""
|
|
120
|
+
The tracks or episodes in the queue. Can be empty.
|
|
121
|
+
|
|
122
|
+
Will be one of the following: `Track` or `Episode`
|
|
123
|
+
"""
|
|
124
|
+
return self._Queue
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def QueueCount(self) -> int:
|
|
129
|
+
"""
|
|
130
|
+
The number of items in the `Queue` array.
|
|
131
|
+
"""
|
|
132
|
+
if self._Queue is not None:
|
|
133
|
+
return len(self._Queue)
|
|
134
|
+
return 0
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def Summary(self) -> str:
|
|
139
|
+
"""
|
|
140
|
+
Returns a summary of what is playing.
|
|
141
|
+
"""
|
|
142
|
+
result:str = ''
|
|
143
|
+
if self._CurrentlyPlaying is not None:
|
|
144
|
+
|
|
145
|
+
if self._CurrentlyPlayingType == SpotifyMediaTypes.TRACK.value:
|
|
146
|
+
track:Track = self._CurrentlyPlaying
|
|
147
|
+
result = 'Track "%s" (%s)' % (track.Name, track.Id)
|
|
148
|
+
elif self._CurrentlyPlayingType == SpotifyMediaTypes.EPISODE.value:
|
|
149
|
+
episode:Episode = self._CurrentlyPlaying
|
|
150
|
+
result = 'Episode "%s" (%s)' % (episode.Name, episode.Id)
|
|
151
|
+
elif self._CurrentlyPlayingType == 'ad':
|
|
152
|
+
result = 'Advertisement'
|
|
153
|
+
|
|
154
|
+
elif self._CurrentlyPlayingType is None:
|
|
155
|
+
|
|
156
|
+
result = 'unavailable'
|
|
157
|
+
|
|
158
|
+
return result
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def ContainsUri(self, uri:str) -> bool:
|
|
162
|
+
"""
|
|
163
|
+
Checks the `Queue` collection to see if an item already exists with the
|
|
164
|
+
specified Uri value.
|
|
165
|
+
|
|
166
|
+
Returns True if the specified Uri value exists in the collection; otherwise, False.
|
|
167
|
+
"""
|
|
168
|
+
result:bool = False
|
|
169
|
+
|
|
170
|
+
if (uri is None):
|
|
171
|
+
return result
|
|
172
|
+
|
|
173
|
+
for item in self._Queue:
|
|
174
|
+
if item.Uri == uri:
|
|
175
|
+
result = True
|
|
176
|
+
break
|
|
177
|
+
|
|
178
|
+
return result
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def ToDictionary(self) -> dict:
|
|
182
|
+
"""
|
|
183
|
+
Returns a dictionary representation of the class.
|
|
184
|
+
"""
|
|
185
|
+
currentlyPlaying:dict = {}
|
|
186
|
+
if self._CurrentlyPlaying is not None:
|
|
187
|
+
currentlyPlaying = self._CurrentlyPlaying.ToDictionary()
|
|
188
|
+
|
|
189
|
+
result:dict = \
|
|
190
|
+
{
|
|
191
|
+
'date_last_refreshed': self._DateLastRefreshed,
|
|
192
|
+
'currently_playing_type': self._CurrentlyPlayingType,
|
|
193
|
+
'currently_playing': currentlyPlaying,
|
|
194
|
+
'queue': [ item.ToDictionary() for item in self._Queue ],
|
|
195
|
+
}
|
|
196
|
+
return result
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def ToString(self) -> str:
|
|
200
|
+
"""
|
|
201
|
+
Returns a displayable string representation of the class.
|
|
202
|
+
"""
|
|
203
|
+
msg:str = 'PlayerQueueInfo:'
|
|
204
|
+
if self._CurrentlyPlayingType is not None: msg = '%s\n CurrentlyPlayingType="%s"' % (msg, str(self._CurrentlyPlayingType))
|
|
205
|
+
if self.QueueCount is not None: msg = '%s\n QueueCount="%s"' % (msg, str(self.QueueCount))
|
|
206
|
+
msg = '%s\n DateLastRefreshed=%s' % (msg, str(self._DateLastRefreshed))
|
|
207
|
+
return msg
|