spotifywebapiPython 1.0.291__py3-none-any.whl → 1.0.293__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 +14 -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/spotifymediatypes.html +2 -2
- spotifywebapipython/docs/spotifywebapipython/spotifytypeprefixes.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 +205 -35
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastapptask.py +1 -1
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastlistener.py +3 -3
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonemanagerlistener.py +6 -6
- spotifywebapipython/zeroconfapi/zeroconfconnect.py +1 -1
- spotifywebapipython/zeroconfapi/zeroconfgetinfo.py +26 -0
- {spotifywebapipython-1.0.291.dist-info → spotifywebapipython-1.0.293.dist-info}/METADATA +1 -1
- {spotifywebapipython-1.0.291.dist-info → spotifywebapipython-1.0.293.dist-info}/RECORD +28 -28
- {spotifywebapipython-1.0.291.dist-info → spotifywebapipython-1.0.293.dist-info}/LICENSE +0 -0
- {spotifywebapipython-1.0.291.dist-info → spotifywebapipython-1.0.293.dist-info}/WHEEL +0 -0
- {spotifywebapipython-1.0.291.dist-info → spotifywebapipython-1.0.293.dist-info}/top_level.txt +0 -0
|
@@ -509,6 +509,108 @@ class SpotifyConnectDirectoryTask(threading.Thread):
|
|
|
509
509
|
# ignore exception, as nothing can be done about it.
|
|
510
510
|
|
|
511
511
|
|
|
512
|
+
def _VerifyMultizoneGroupLeader(
|
|
513
|
+
self,
|
|
514
|
+
scDevice: SpotifyConnectDevice,
|
|
515
|
+
discoveryResult: ZeroconfDiscoveryResult,
|
|
516
|
+
) -> None:
|
|
517
|
+
"""
|
|
518
|
+
Verifies the current leader for a cast group is connected and available.
|
|
519
|
+
|
|
520
|
+
Args:
|
|
521
|
+
scDevice (SpotifyConnectDevice):
|
|
522
|
+
SpotifyConnectDevice object that contains discovery result details.
|
|
523
|
+
discoveryResult (ZeroconfDiscoveryResult):
|
|
524
|
+
Newly discovered zeroconf updates for the device.
|
|
525
|
+
"""
|
|
526
|
+
try:
|
|
527
|
+
|
|
528
|
+
leaderIP:str|None = None
|
|
529
|
+
|
|
530
|
+
# the MultiZoneManager should already have processed any multi-zone updates,
|
|
531
|
+
# including leadership changes; all we need to do now is to get the ChromeCast
|
|
532
|
+
# device reference from it, and retrieve the host IP address.
|
|
533
|
+
|
|
534
|
+
# if the Chromecast device socket client reports a different host IP address
|
|
535
|
+
# than it's CastInfo object, then it means that the multizone manager update
|
|
536
|
+
# is out of sync with the mDNS update! if that is the case, then we need to
|
|
537
|
+
# determine which of the two (if any!) is the active group leader.
|
|
538
|
+
|
|
539
|
+
# get group info from the multizone manager instance.
|
|
540
|
+
groupInfo = self._CastMultiZoneManager._groups.get(scDevice.DiscoveryResult.Key, None)
|
|
541
|
+
if (groupInfo is not None):
|
|
542
|
+
|
|
543
|
+
# get the assumed group leader device reference.
|
|
544
|
+
castDevice:Chromecast = groupInfo.get('chromecast', None)
|
|
545
|
+
if (castDevice):
|
|
546
|
+
|
|
547
|
+
if (castDevice.socket_client) and (castDevice.socket_client.is_connected):
|
|
548
|
+
leaderIP = castDevice.socket_client.host
|
|
549
|
+
|
|
550
|
+
elif (castDevice.cast_info):
|
|
551
|
+
leaderIP = castDevice.cast_info.host
|
|
552
|
+
|
|
553
|
+
# do we have a group leader conflict between the multizone manager
|
|
554
|
+
# reference and the mDNS service update?
|
|
555
|
+
if (leaderIP != discoveryResult.HostIpAddress):
|
|
556
|
+
|
|
557
|
+
# at this point, mDNS information is in conflict with MultiZoneManager information
|
|
558
|
+
# about who the group leader is! we will now query BOTH addresses to see which one
|
|
559
|
+
# responds, and use it as the group leader.
|
|
560
|
+
|
|
561
|
+
# trace.
|
|
562
|
+
_logsi.LogVerbose("Group leader conflict detected for device UUID: \"%s\"" % discoveryResult.Key)
|
|
563
|
+
|
|
564
|
+
try:
|
|
565
|
+
|
|
566
|
+
# connect to the first possible group leader.
|
|
567
|
+
_logsi.LogVerbose("Connecting to possible Cast Group leader #1: \"%s\"" % (discoveryResult.HostIpAddress))
|
|
568
|
+
castDevice = get_chromecast_from_host(
|
|
569
|
+
host=(discoveryResult.HostIpAddress, discoveryResult.HostIpPort, discoveryResult.Key, scDevice.DeviceInfo.ModelDisplayName, scDevice.DeviceInfo.RemoteName),
|
|
570
|
+
tries=1,
|
|
571
|
+
retry_wait=0.5,
|
|
572
|
+
timeout=2)
|
|
573
|
+
|
|
574
|
+
# if connection was successful, then use it as the leader.
|
|
575
|
+
leaderIP = discoveryResult.HostIpAddress
|
|
576
|
+
|
|
577
|
+
except Exception as ex:
|
|
578
|
+
|
|
579
|
+
try:
|
|
580
|
+
|
|
581
|
+
# connect to the first possible group leader.
|
|
582
|
+
_logsi.LogVerbose("Connecting to possible Cast Group leader #2: \"%s\"" % (leaderIP))
|
|
583
|
+
castDevice = get_chromecast_from_host(
|
|
584
|
+
host=(leaderIP, scDevice.DiscoveryResult.HostIpPort, scDevice.DiscoveryResult.Key, scDevice.DeviceInfo.ModelDisplayName, scDevice.DeviceInfo.RemoteName),
|
|
585
|
+
tries=1,
|
|
586
|
+
retry_wait=0.5,
|
|
587
|
+
timeout=2)
|
|
588
|
+
|
|
589
|
+
# if connection was successful, then use it as the leader.
|
|
590
|
+
leaderIP = leaderIP
|
|
591
|
+
|
|
592
|
+
except Exception as ex:
|
|
593
|
+
|
|
594
|
+
_logsi.LogVerbose("Could not connect to either possible Cast Group leader for device: \"%s\"" % (scDevice.Title))
|
|
595
|
+
|
|
596
|
+
# free resources.
|
|
597
|
+
castDevice = None
|
|
598
|
+
|
|
599
|
+
# do we have a group leader change?
|
|
600
|
+
if (leaderIP != scDevice.DiscoveryResult.HostIpAddress):
|
|
601
|
+
|
|
602
|
+
# trace.
|
|
603
|
+
_logsi.LogObject(SILevel.Verbose, "Cast Group leader IP was changed from [%s] to [%s] for device \"%s\"" % (scDevice.DiscoveryResult.HostIpAddress, leaderIP, scDevice.Name), scDevice, excludeNonPublic=True, colorValue=SIColors.ForestGreen)
|
|
604
|
+
scDevice.DiscoveryResult.HostIpAddress = leaderIP
|
|
605
|
+
scDevice.DiscoveryResult.Id = "\"%s\" (%s:%s)" % (scDevice.DiscoveryResult.DeviceName, scDevice.DiscoveryResult.HostIpAddress, scDevice.DiscoveryResult.HostIpPort)
|
|
606
|
+
|
|
607
|
+
except Exception as ex:
|
|
608
|
+
|
|
609
|
+
# trace.
|
|
610
|
+
_logsi.LogException("Chromecast Multizone group leader query exception: %s" % (str(ex)), ex, logToSystemLogger=False)
|
|
611
|
+
# ignore exception, as nothing can be done about it.
|
|
612
|
+
|
|
613
|
+
|
|
512
614
|
def ActivateCastAppSpotify(
|
|
513
615
|
self,
|
|
514
616
|
deviceName:str,
|
|
@@ -586,6 +688,13 @@ class SpotifyConnectDirectoryTask(threading.Thread):
|
|
|
586
688
|
# match was found; reset device id activated before we activate a device.
|
|
587
689
|
scDevice.DeviceIdActivated = None
|
|
588
690
|
|
|
691
|
+
# is the activation request for a group?
|
|
692
|
+
if (scDevice.DiscoveryResult.IsChromeCastGroup):
|
|
693
|
+
|
|
694
|
+
# verify the current leader of the group.
|
|
695
|
+
# the device collection entry will be updated if a change was detected.
|
|
696
|
+
self._VerifyMultizoneGroupLeader(scDevice, scDevice.DiscoveryResult)
|
|
697
|
+
|
|
589
698
|
# is this a chromecast device?
|
|
590
699
|
if (not scDevice.IsChromeCast):
|
|
591
700
|
raise SpotifyApiError("Device %s is not a Chromecast device; use TransferPlayback instead." % (scDevice.Title), logsi=_logsi)
|
|
@@ -1997,17 +2106,27 @@ class SpotifyConnectDirectoryTask(threading.Thread):
|
|
|
1997
2106
|
scDevice.DeviceInfo.RemoteName = newDeviceName
|
|
1998
2107
|
deviceNameChanged = True
|
|
1999
2108
|
|
|
2000
|
-
# is this a Google Cast Group
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2109
|
+
# is this a Google Cast Group update?
|
|
2110
|
+
if (zeroconfDiscoveryResult.IsChromeCastGroup):
|
|
2111
|
+
|
|
2112
|
+
# is this a Google Cast Group "add_cast" event?
|
|
2113
|
+
# if so, then it's probably a group leadership change that did not issue a call to
|
|
2114
|
+
# "remove_cast" as part of the update. we now have to determine which device in the
|
|
2115
|
+
# group is the new leader, and update the group DiscoveryResult accordingly.
|
|
2116
|
+
if (serviceType == "add_cast"):
|
|
2007
2117
|
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2118
|
+
# verify the current leader of the group.
|
|
2119
|
+
# the device collection entry will be updated if a change was detected.
|
|
2120
|
+
self._VerifyMultizoneGroupLeader(scDevice, zeroconfDiscoveryResult)
|
|
2121
|
+
|
|
2122
|
+
# is this a Google Cast Group "update_cast" event?
|
|
2123
|
+
# if so, AND the device name did not change, then ignore the update since
|
|
2124
|
+
# we will pickup any group leader changes in the ActivateCastAppSpotify method.
|
|
2125
|
+
elif (serviceType == "update_cast") and (not deviceNameChanged):
|
|
2126
|
+
|
|
2127
|
+
_logsi.LogObject(SILevel.Verbose, "SpotifyConnectDevice info: \"%s\" (ignored; Cast Group device update)" % (scDevice.Name), scDevice.DiscoveryResult, excludeNonPublic=True)
|
|
2128
|
+
_logsi.LogObject(SILevel.Debug, "SpotifyConnectDevice info: %s (NEW DiscoveryResult ignored) [%s]" % (scDevice.Title, zeroconfDiscoveryResult.HostIpTitle), zeroconfDiscoveryResult, excludeNonPublic=True)
|
|
2129
|
+
return
|
|
2011
2130
|
|
|
2012
2131
|
# set zeroconf discovery result properties.
|
|
2013
2132
|
scDevice.DiscoveryResult = zeroconfDiscoveryResult
|
|
@@ -2312,6 +2431,8 @@ class SpotifyConnectDirectoryTask(threading.Thread):
|
|
|
2312
2431
|
# syncronize access via lock, as we are accessing the collection.
|
|
2313
2432
|
with self._SpotifyConnectDevices_RLock:
|
|
2314
2433
|
|
|
2434
|
+
zconn:ZeroconfConnect = None
|
|
2435
|
+
|
|
2315
2436
|
try:
|
|
2316
2437
|
|
|
2317
2438
|
# trace.
|
|
@@ -2374,20 +2495,13 @@ class SpotifyConnectDirectoryTask(threading.Thread):
|
|
|
2374
2495
|
# retrieve initial spotify connect device information (by ip address).
|
|
2375
2496
|
scDevice.DeviceInfo = zconn.GetInformation()
|
|
2376
2497
|
scDevice.Id = scDevice.DeviceInfo.DeviceId
|
|
2377
|
-
scDevice.Name = scDevice.DeviceInfo.
|
|
2498
|
+
scDevice.Name = scDevice.DeviceInfo.RemoteNameOrAlias
|
|
2378
2499
|
|
|
2379
2500
|
# if service discovery version not set, then use the getInfo version.
|
|
2380
2501
|
if (zeroconfDiscoveryResult.SpotifyConnectVersion is None):
|
|
2381
2502
|
if (scDevice.DeviceInfo.Version is not None):
|
|
2382
2503
|
zeroconfDiscoveryResult.SpotifyConnectVersion = scDevice.DeviceInfo.Version
|
|
2383
2504
|
|
|
2384
|
-
# if remote name was not specified, then set device name to first alias name.
|
|
2385
|
-
# note that we will not reset the RemoteName, as the "" value indicates an alias is in use.
|
|
2386
|
-
if ((scDevice.DeviceInfo.RemoteName + "").strip() == ""):
|
|
2387
|
-
if (scDevice.DeviceInfo.HasAliases):
|
|
2388
|
-
_logsi.LogVerbose("Spotify Connect Zeroconf GetInformation alias name will be utilized for Zeroconf Discovery Result: \"%s\" (%s)" % (zeroconfDiscoveryResult.DeviceName, zeroconfDiscoveryResult.Name))
|
|
2389
|
-
scDevice.Name = scDevice.DeviceInfo.Aliases[0].Name
|
|
2390
|
-
|
|
2391
2505
|
except Exception as ex:
|
|
2392
2506
|
|
|
2393
2507
|
# trace.
|
|
@@ -2413,20 +2527,13 @@ class SpotifyConnectDirectoryTask(threading.Thread):
|
|
|
2413
2527
|
# retrieve initial spotify connect device information (by dns alias).
|
|
2414
2528
|
scDevice.DeviceInfo = zconn.GetInformation()
|
|
2415
2529
|
scDevice.Id = scDevice.DeviceInfo.DeviceId
|
|
2416
|
-
scDevice.Name = scDevice.DeviceInfo.
|
|
2530
|
+
scDevice.Name = scDevice.DeviceInfo.RemoteNameOrAlias
|
|
2417
2531
|
|
|
2418
2532
|
# if service discovery version not set, then use the getInfo version.
|
|
2419
2533
|
if (zeroconfDiscoveryResult.SpotifyConnectVersion is None):
|
|
2420
2534
|
if (scDevice.DeviceInfo.Version is not None):
|
|
2421
2535
|
zeroconfDiscoveryResult.SpotifyConnectVersion = scDevice.DeviceInfo.Version
|
|
2422
2536
|
|
|
2423
|
-
# if remote name was not specified, then set device name to first alias name.
|
|
2424
|
-
# note that we will not reset the RemoteName, as the "" value indicates an alias is in use.
|
|
2425
|
-
if ((scDevice.DeviceInfo.RemoteName + "").strip() == ""):
|
|
2426
|
-
if (scDevice.DeviceInfo.HasAliases):
|
|
2427
|
-
_logsi.LogVerbose("Spotify Connect Zeroconf GetInformation alias name will be utilized for Zeroconf Discovery Result: \"%s\" (%s)" % (zeroconfDiscoveryResult.DeviceName, zeroconfDiscoveryResult.Name))
|
|
2428
|
-
scDevice.Name = scDevice.DeviceInfo.Aliases[0].Name
|
|
2429
|
-
|
|
2430
2537
|
# update HostIpAddress in discovery result so it knows to use the dns alias
|
|
2431
2538
|
# instead of the ip address.
|
|
2432
2539
|
_logsi.LogVerbose("Spotify Connect Zeroconf GetInformation call for Instance Name \"%s\" (%s) was resolved using DNS Server alias; HostIpAddress will be updated with the resolved ip address" % (zeroconfDiscoveryResult.DeviceName, zeroconfDiscoveryResult.Server))
|
|
@@ -2526,25 +2633,84 @@ class SpotifyConnectDirectoryTask(threading.Thread):
|
|
|
2526
2633
|
scDevice = self._SpotifyConnectDevices.Items[idx]
|
|
2527
2634
|
|
|
2528
2635
|
# were any changes made to the zeroconf discovery results?
|
|
2636
|
+
# this can happen when the Spotify Connect zeroconf server on the device has
|
|
2637
|
+
# been restarted (e.g. "resetUsers" called, etc). if so, then we need to update
|
|
2638
|
+
# the DiscoveryResult since it could possibly point to a different host address
|
|
2639
|
+
# (or port number) for the zeroconf endpoints (e.g. getInfo, addUser, etc). we will
|
|
2640
|
+
# also call "getInfo" to update any Spotify Connect changes (e.g. RemoteName, Id, etc).
|
|
2529
2641
|
if (not scDevice.DiscoveryResult.Equals(zeroconfDiscoveryResult)):
|
|
2530
2642
|
|
|
2531
2643
|
# trace.
|
|
2644
|
+
_logsi.LogVerbose("Spotify Connect zeroconf DiscoveryResult change detected for device: %s" % (scDevice.Title))
|
|
2532
2645
|
_logsi.LogObject(SILevel.Debug, "SpotifyConnectDevice info: \"%s\" (OLD DeviceInfo / getInfo)" % (scDevice.Title), scDevice.DeviceInfo, excludeNonPublic=True)
|
|
2533
2646
|
_logsi.LogObject(SILevel.Debug, "SpotifyConnectDevice info: \"%s\" (OLD DiscoveryResult) [%s]" % (scDevice.Title, scDevice.DiscoveryResult.HostIpTitle), scDevice.DiscoveryResult, excludeNonPublic=True)
|
|
2534
2647
|
|
|
2535
|
-
#
|
|
2648
|
+
# preserve various old property values for comparison later.
|
|
2649
|
+
oldDeviceId:str = scDevice.DeviceInfo.DeviceId
|
|
2650
|
+
oldRemoteName:str = scDevice.DeviceInfo.RemoteNameOrAlias
|
|
2651
|
+
oldHostIpPort:int = scDevice.DiscoveryResult.HostIpPort
|
|
2652
|
+
newRemoteName:str = None
|
|
2653
|
+
newDeviceId:str = None
|
|
2654
|
+
|
|
2655
|
+
try:
|
|
2656
|
+
|
|
2657
|
+
# trace.
|
|
2658
|
+
_logsi.LogVerbose("Retrieving Spotify Connect device information: %s [DiscoveryResult change]" % (zeroconfDiscoveryResult.Id))
|
|
2659
|
+
|
|
2660
|
+
# create connection object to retrieve spotify connect device information (via direct ip address).
|
|
2661
|
+
zconn:ZeroconfConnect = ZeroconfConnect(
|
|
2662
|
+
zeroconfDiscoveryResult.HostIpAddress,
|
|
2663
|
+
zeroconfDiscoveryResult.HostIpPort,
|
|
2664
|
+
zeroconfDiscoveryResult.SpotifyConnectCPath,
|
|
2665
|
+
zeroconfDiscoveryResult.SpotifyConnectVersion,
|
|
2666
|
+
useSSL=False,
|
|
2667
|
+
tokenStorageDir=self.SpotifyClientInstance.TokenStorageDir,
|
|
2668
|
+
tokenStorageFile=self.SpotifyClientInstance.TokenStorageFile
|
|
2669
|
+
)
|
|
2670
|
+
|
|
2671
|
+
# retrieve spotify connect device information (by ip address).
|
|
2672
|
+
getInfo:ZeroconfGetInfo = zconn.GetInformation()
|
|
2673
|
+
|
|
2674
|
+
# if service discovery version not set, then use the getInfo version.
|
|
2675
|
+
if (zeroconfDiscoveryResult.SpotifyConnectVersion is None):
|
|
2676
|
+
if (getInfo.Version is not None):
|
|
2677
|
+
zeroconfDiscoveryResult.SpotifyConnectVersion = getInfo.Version
|
|
2678
|
+
|
|
2679
|
+
# update base device info from getInfo details.
|
|
2680
|
+
scDevice.DeviceInfo = getInfo
|
|
2681
|
+
|
|
2682
|
+
# set device name and id values from getInfo response values.
|
|
2683
|
+
newRemoteName = getInfo.RemoteNameOrAlias
|
|
2684
|
+
newDeviceId = getInfo.DeviceId
|
|
2685
|
+
|
|
2686
|
+
except Exception as ex:
|
|
2687
|
+
|
|
2688
|
+
# trace.
|
|
2689
|
+
_logsi.LogVerbose("Could not retrieve Spotify Connect device information; defaulting DeviceID to GetSpotifyDeviceIDFromName \"%s\"" % (zeroconfDiscoveryResult.DeviceName))
|
|
2690
|
+
|
|
2691
|
+
# at this point we don't know for sure what the device name is since getInfo failed.
|
|
2692
|
+
# set device name and id values from serviceinfo discovery values.
|
|
2693
|
+
newRemoteName:str = zeroconfDiscoveryResult.DeviceName
|
|
2694
|
+
newDeviceId:str = self.GetSpotifyDeviceIDFromName(newRemoteName)
|
|
2695
|
+
|
|
2696
|
+
# update zeroconf discovery result properties in the base device object.
|
|
2536
2697
|
scDevice.DiscoveryResult = zeroconfDiscoveryResult
|
|
2537
2698
|
|
|
2538
|
-
# did the device name change?
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2699
|
+
# did the device remote name change? if so, then update base device properties.
|
|
2700
|
+
if (oldRemoteName != newRemoteName):
|
|
2701
|
+
_logsi.LogVerbose("Spotify Connect Zeroconf device RemoteNameAlias changed from \"%s\" to \"%s\"" % (oldRemoteName, newRemoteName))
|
|
2702
|
+
scDevice.Name = newRemoteName
|
|
2703
|
+
scDevice.DeviceInfo.RemoteName = newRemoteName
|
|
2704
|
+
|
|
2705
|
+
# did the device id change?
|
|
2706
|
+
if (oldDeviceId != newDeviceId):
|
|
2707
|
+
_logsi.LogVerbose("Spotify Connect Zeroconf device Id changed from \"%s\" to \"%s\"" % (oldDeviceId, newDeviceId))
|
|
2545
2708
|
scDevice.Id = newDeviceId
|
|
2546
2709
|
scDevice.DeviceInfo.DeviceId = newDeviceId
|
|
2547
|
-
|
|
2710
|
+
|
|
2711
|
+
# did the device zeroconf server listener port change?
|
|
2712
|
+
if (oldHostIpPort != zeroconfDiscoveryResult.HostIpPort):
|
|
2713
|
+
_logsi.LogVerbose("Spotify Connect Zeroconf device HostIpPort changed from \"%s\" to \"%s\"" % (oldHostIpPort, zeroconfDiscoveryResult.HostIpPort))
|
|
2548
2714
|
|
|
2549
2715
|
# update existing Spotify Connect Device in devices collection.
|
|
2550
2716
|
self._SpotifyConnectDevices.Items[idx] = scDevice
|
|
@@ -2576,6 +2742,10 @@ class SpotifyConnectDirectoryTask(threading.Thread):
|
|
|
2576
2742
|
|
|
2577
2743
|
finally:
|
|
2578
2744
|
|
|
2745
|
+
# free resources.
|
|
2746
|
+
if (zconn is not None):
|
|
2747
|
+
zconn = None
|
|
2748
|
+
|
|
2579
2749
|
# trace.
|
|
2580
2750
|
_logsi.LeaveMethod(SILevel.Debug)
|
|
2581
2751
|
|
|
@@ -393,7 +393,7 @@ class SpotifyConnectZeroconfCastAppTask(threading.Thread):
|
|
|
393
393
|
loginId:str,
|
|
394
394
|
) -> SpotifyAuthToken:
|
|
395
395
|
"""
|
|
396
|
-
Retrieve Spotify Desktop
|
|
396
|
+
Retrieve Spotify Desktop authorization access token from the token cache file.
|
|
397
397
|
The resulting token will be used to launch the Spotify cast app.
|
|
398
398
|
"""
|
|
399
399
|
apiMethodName:str = '_GetSpotifyDesktopAuthorizationToken'
|
|
@@ -91,10 +91,10 @@ class SpotifyConnectZeroconfCastListener(AbstractCastListener):
|
|
|
91
91
|
|
|
92
92
|
try:
|
|
93
93
|
|
|
94
|
-
# is this an
|
|
95
|
-
# that contain
|
|
94
|
+
# is this an GoogleCast service record? we only want discovery results
|
|
95
|
+
# that contain GoogleCast service information.
|
|
96
96
|
if (serviceName.find(ZEROCONF_SERVICETYPE_GOOGLECAST) == -1):
|
|
97
|
-
_logsi.LogDebug("Chromecast Zeroconf discovery service notification: \"%s\" (%s)" % (serviceName, "ignored; not
|
|
97
|
+
_logsi.LogDebug("Chromecast Zeroconf discovery service notification: \"%s\" (%s)" % (serviceName, "ignored; not GoogleCast service type"))
|
|
98
98
|
return None
|
|
99
99
|
|
|
100
100
|
# get chromecast info.
|
|
@@ -113,9 +113,9 @@ class SpotifyConnectZeroconfCastMultiZoneManagerListener(MultiZoneManagerListene
|
|
|
113
113
|
# trace.
|
|
114
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
115
|
|
|
116
|
-
#
|
|
117
|
-
|
|
118
|
-
|
|
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
119
|
|
|
120
120
|
# # build member list with friendly names.
|
|
121
121
|
# result:list[str] = []
|
|
@@ -185,9 +185,9 @@ class SpotifyConnectZeroconfCastMultiZoneManagerListener(MultiZoneManagerListene
|
|
|
185
185
|
# trace.
|
|
186
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
187
|
|
|
188
|
-
#
|
|
189
|
-
|
|
190
|
-
|
|
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
191
|
|
|
192
192
|
# # build member list with friendly names.
|
|
193
193
|
# result:list[str] = []
|
|
@@ -1497,7 +1497,7 @@ class ZeroconfConnect:
|
|
|
1497
1497
|
result = ZeroconfGetInfo(root=responseData)
|
|
1498
1498
|
|
|
1499
1499
|
# trace.
|
|
1500
|
-
_logsi.LogObject(SILevel.Verbose, '%s result (%s) - "%s" (%s)' % (apiMethodName, type(result).__name__, result.
|
|
1500
|
+
_logsi.LogObject(SILevel.Verbose, '%s result (%s) - "%s" (%s)' % (apiMethodName, type(result).__name__, result.RemoteNameOrAlias, result.DeviceId), result, excludeNonPublic=True)
|
|
1501
1501
|
|
|
1502
1502
|
# if result status is not ok, then raise an exception.
|
|
1503
1503
|
if (result.Status != 101):
|
|
@@ -373,6 +373,32 @@ class ZeroconfGetInfo(ZeroconfResponse):
|
|
|
373
373
|
if (isinstance(value, str)) or (value is None):
|
|
374
374
|
self._RemoteName = value
|
|
375
375
|
|
|
376
|
+
@property
|
|
377
|
+
def RemoteNameOrAlias(self) -> str:
|
|
378
|
+
"""
|
|
379
|
+
Name to be displayed for the device (e.g. "BOSE-ST10-1").
|
|
380
|
+
|
|
381
|
+
If a RemoteName value is not defined, then the first alias name will be
|
|
382
|
+
returned if one is defined.
|
|
383
|
+
|
|
384
|
+
This value will be null if the response does not contain a RemoteName value
|
|
385
|
+
and there are no Aliases defined.
|
|
386
|
+
"""
|
|
387
|
+
if (self._RemoteName is not None) and ((self._RemoteName + "").strip() != ""):
|
|
388
|
+
|
|
389
|
+
# if remote name is defined, then return it.
|
|
390
|
+
return self._RemoteName
|
|
391
|
+
|
|
392
|
+
elif (self.HasAliases):
|
|
393
|
+
|
|
394
|
+
# if aliases are defined then return the first alias name.
|
|
395
|
+
return self._Aliases[0].Name
|
|
396
|
+
|
|
397
|
+
else:
|
|
398
|
+
|
|
399
|
+
# otherwise return null.
|
|
400
|
+
return None
|
|
401
|
+
|
|
376
402
|
|
|
377
403
|
@property
|
|
378
404
|
def ResolverVersion(self) -> str:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
spotifywebapipython/__init__.py,sha256=ka7F2AsT-UU7KSYKBnfgl5Trojcep5aQspLutg8D-2k,1306
|
|
2
|
-
spotifywebapipython/const.py,sha256
|
|
2
|
+
spotifywebapipython/const.py,sha256=-MK2XDNRlk4nSX1I6Twnb2dFpTTmbjhhG-pUuU7EVJ8,4100
|
|
3
3
|
spotifywebapipython/saappmessages.py,sha256=mVprjpd5CdD8kYeAkLzRvMvIQPmaYtH4UCP5my3QhSk,5065
|
|
4
4
|
spotifywebapipython/sautils.py,sha256=LZF3UvxaBK35WIg1hO37nbW8j1y-M-oOxRbi1dPR39w,8746
|
|
5
5
|
spotifywebapipython/spotifyapierror.py,sha256=23_CYlxWN0BceYYCLpBpunl55vEwPr_wFf34l74xzeA,1855
|
|
@@ -12,25 +12,25 @@ spotifywebapipython/spotifytypeprefixes.py,sha256=3yfpxKF7jF694qBuo-PbKYvm70Ywwd
|
|
|
12
12
|
spotifywebapipython/spotifywebapiauthenticationerror.py,sha256=5A0MKvYo3Ypv0ZeSSfLHuFLwzoUUu044bBoUgMfNXNw,3940
|
|
13
13
|
spotifywebapipython/spotifywebapierror.py,sha256=ctYFvkBPlFFEoM_geP6hzwTyC2mPcrYR_zCCNvsmpwc,3870
|
|
14
14
|
spotifywebapipython/spotifywebplayertoken.py,sha256=axj1j1lM7COiiZfpElkJRdnk4AmE6bAQcjKshUIz1Nk,35813
|
|
15
|
-
spotifywebapipython/docs/__init__.html,sha256=
|
|
15
|
+
spotifywebapipython/docs/__init__.html,sha256=BbgVYepvDBcuFDlCXiaHEL7zC_AOhE_wzbaSQSHHdZA,199550
|
|
16
16
|
spotifywebapipython/docs/codecopy.js,sha256=ryuoZwLIL03YitjjFzn49UO5ta7-OBos6LNA3qHhFzs,3120
|
|
17
|
-
spotifywebapipython/docs/index.html,sha256=
|
|
18
|
-
spotifywebapipython/docs/search.js,sha256=
|
|
17
|
+
spotifywebapipython/docs/index.html,sha256=G7d3zqwSjXIfUzejBK7Mq8mXp5p_jPHibD-fZDdnCQQ,48779
|
|
18
|
+
spotifywebapipython/docs/search.js,sha256=NBEMS22T3h_v3zyLYwTxdYfPjP6DjkGzjwtAiOTBPDM,9277254
|
|
19
19
|
spotifywebapipython/docs/spotifywebapipython.ico,sha256=YImj39fqqSPSuB2-sMDlUYDd6YwRfQeJRtq4FjwWglg,16410
|
|
20
20
|
spotifywebapipython/docs/spotifywebapipython_OLD.ico,sha256=YIv5LjcD4bTIJQSOr8jjwbWaeB3QkElRwkTOePiGbZo,14904
|
|
21
|
-
spotifywebapipython/docs/spotifywebapipython/const.html,sha256=
|
|
22
|
-
spotifywebapipython/docs/spotifywebapipython/saappmessages.html,sha256=
|
|
23
|
-
spotifywebapipython/docs/spotifywebapipython/sautils.html,sha256=
|
|
24
|
-
spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html,sha256=
|
|
25
|
-
spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html,sha256=
|
|
26
|
-
spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html,sha256=
|
|
27
|
-
spotifywebapipython/docs/spotifywebapipython/spotifyclient.html,sha256=
|
|
28
|
-
spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html,sha256=
|
|
29
|
-
spotifywebapipython/docs/spotifywebapipython/spotifymediatypes.html,sha256=
|
|
30
|
-
spotifywebapipython/docs/spotifywebapipython/spotifytypeprefixes.html,sha256=
|
|
31
|
-
spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html,sha256=
|
|
32
|
-
spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html,sha256=
|
|
33
|
-
spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html,sha256=
|
|
21
|
+
spotifywebapipython/docs/spotifywebapipython/const.html,sha256=8ChDCvi6QQPh53FVTeAu3WvbcBcH9WULzCO-G-KYJ0s,60537
|
|
22
|
+
spotifywebapipython/docs/spotifywebapipython/saappmessages.html,sha256=DFbB_WMia4awIQRDgVsK_X8TcdAfskruROq2uls9Lfw,62358
|
|
23
|
+
spotifywebapipython/docs/spotifywebapipython/sautils.html,sha256=r22R4943nFwfNOlwbOGOVOJ8V9nGyf77gHeuYDbn01Y,62031
|
|
24
|
+
spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html,sha256=zk6ISCkMNVot-9B2nN4DYsbZofqXEoadk4i2eV97L0c,48054
|
|
25
|
+
spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html,sha256=bSh2AebWNGHHO7kApEKDGjOgrj8JCnlx1Se39XZ1O2U,59210
|
|
26
|
+
spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html,sha256=zjxALxnn7mDoPVLFPZXM0jdpoOS-CoaHvLLl4e2WnBs,59256
|
|
27
|
+
spotifywebapipython/docs/spotifywebapipython/spotifyclient.html,sha256=RsHNAUyjZIN2tEOSADjNX2CGow3RLeftgqLCgluoanM,1677607
|
|
28
|
+
spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html,sha256=gN5dBTv6fmQloEQgRpSw2bKuMQu9eksb_2BYYUPgJZY,57662
|
|
29
|
+
spotifywebapipython/docs/spotifywebapipython/spotifymediatypes.html,sha256=oy0ohUZbpNGqAf51EdnuwtwRpLzHhr2bRDa_DxbuHuc,51532
|
|
30
|
+
spotifywebapipython/docs/spotifywebapipython/spotifytypeprefixes.html,sha256=7qGYuGomj0QLXxSXNiLlQAkyHyzs4R4WiMVyzFn3kkw,52401
|
|
31
|
+
spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html,sha256=NEZDhVACveFhv1xWKJcT9pj1C5CGHgxlWslMKKcfeFQ,52174
|
|
32
|
+
spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html,sha256=n0bFI8907vW8ApggdbpCtPW_M6_gzGx4LgPL9WqpRA8,51484
|
|
33
|
+
spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html,sha256=HqxGXcIapwRbcHvR4lGTRkG4xdn-xrFXr9TZ1Bx8o28,62204
|
|
34
34
|
spotifywebapipython/models/__init__.py,sha256=RwRQhUX-6EUs8XvStVFpR8EPwoqIAz9K6ref-28qHKI,4423
|
|
35
35
|
spotifywebapipython/models/album.py,sha256=U3Pdw0-EL33LdkeiN31fjZ23rlLk6DNGV8jRmZU7EyQ,5170
|
|
36
36
|
spotifywebapipython/models/albumpagesaved.py,sha256=SBYMhkh5ZsMrRAXl-cm9zsxMDh8gO190ENq6Py2TyGY,2417
|
|
@@ -110,12 +110,12 @@ spotifywebapipython/oauthcli/__init__.py,sha256=K37XTxYAKT0n8otCNzWbjgJ10fAPN4WL
|
|
|
110
110
|
spotifywebapipython/oauthcli/authclient.py,sha256=qGKa4FLBHHZQyP5ho1sIM_mNmyshQd720YwKcUFQJAw,56207
|
|
111
111
|
spotifywebapipython/spotifyconnect/__init__.py,sha256=9Xl5KiJFvWLbsdb4YQ0xmF67i36ybpXCCXrWeNsKEvc,1108
|
|
112
112
|
spotifywebapipython/spotifyconnect/spotifyconnectdeviceeventargs.py,sha256=35hKa0FAaPgy7W8D6MFXmga667pjwXITo8jSj1TDfE8,1988
|
|
113
|
-
spotifywebapipython/spotifyconnect/spotifyconnectdirectorytask.py,sha256=
|
|
114
|
-
spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastapptask.py,sha256=
|
|
113
|
+
spotifywebapipython/spotifyconnect/spotifyconnectdirectorytask.py,sha256=1VQG5qY0mSoi0wdPV0ltOrzjtsLlAi79D-br1ve41nE,163817
|
|
114
|
+
spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastapptask.py,sha256=jArxsjAGntTcQD9L9yVuey1L8pw0KvshlNXIBA7PqiI,23367
|
|
115
115
|
spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastcontroller.py,sha256=e2wLmFq4393IdVa51w8X5UQl4KfnHRh34DMlxZfl9-g,34218
|
|
116
|
-
spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastlistener.py,sha256=
|
|
116
|
+
spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastlistener.py,sha256=EBrKZfkiAY-_UiEBXCa7sPpH1lip4Gz1bNwT1fWc1LE,16712
|
|
117
117
|
spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonecontrollerlistener.py,sha256=AA-XxS6AptJWzyO2zsM9DA5ioCncJBKDTpJkr_aN9IM,12352
|
|
118
|
-
spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonemanagerlistener.py,sha256=
|
|
118
|
+
spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonemanagerlistener.py,sha256=gA-R7nR5cRbHrLVEGIRQILry72MSVpub4pNW-DZHWRY,18906
|
|
119
119
|
spotifywebapipython/spotifyconnect/spotifyconnectzeroconfexceptions.py,sha256=aesGauxMoKupdTPR5rL2-rXBC3SEvH_9bQQx2Vh-abs,524
|
|
120
120
|
spotifywebapipython/spotifyconnect/spotifyconnectzeroconflistener.py,sha256=ciN31zub2gk9On-1Gf7xDQpOdCEA3mutYIXpVfuA-w0,16583
|
|
121
121
|
spotifywebapipython/vibrant/__init__.py,sha256=x3yGfhH0ydjWTSILADuwQXaoLvpkV2EM0T_gyZ5aX38,712
|
|
@@ -132,13 +132,13 @@ spotifywebapipython/zeroconfapi/credentials.py,sha256=MIXqZvFNDjoICpZGNXPveHNl9G
|
|
|
132
132
|
spotifywebapipython/zeroconfapi/cryptodiffiehellman.py,sha256=k-nMR68GtzODYsQrwCpvFE2XNxv-XUFbMemplldtwp4,3340
|
|
133
133
|
spotifywebapipython/zeroconfapi/helpers.py,sha256=9lJFOuKYrk-e7SbU94WmFv5oiBq4k5gMS8wE1it4Wbc,1429
|
|
134
134
|
spotifywebapipython/zeroconfapi/spotifyzeroconfapierror.py,sha256=rTwIrr1qV0UiQS_zBufboyZ3A3yGrdCsTAOiVA5dvzY,3031
|
|
135
|
-
spotifywebapipython/zeroconfapi/zeroconfconnect.py,sha256=
|
|
136
|
-
spotifywebapipython/zeroconfapi/zeroconfgetinfo.py,sha256=
|
|
135
|
+
spotifywebapipython/zeroconfapi/zeroconfconnect.py,sha256=JzAKVc7XC_HrTH1IwsuXpcgW0rFlRYocHL8likoYYvQ,79023
|
|
136
|
+
spotifywebapipython/zeroconfapi/zeroconfgetinfo.py,sha256=gTr3J3iVDR_ueP1tg-WHuCOke3eP864WGiESmOOYFUw,22243
|
|
137
137
|
spotifywebapipython/zeroconfapi/zeroconfgetinfoalias.py,sha256=FZJM23HIPJSfhXIC3-EuS1XhawheoG5maSp7__k4yBo,2932
|
|
138
138
|
spotifywebapipython/zeroconfapi/zeroconfgetinfodrmmediaformat.py,sha256=c5uk8ljsIuBK3w2jahHKQuoWvm245LOjUBitetXx5Mo,2347
|
|
139
139
|
spotifywebapipython/zeroconfapi/zeroconfresponse.py,sha256=mAPIDj5MG53x8peiScrp7OJblwy_o_Sto4wqE0rGujU,6445
|
|
140
|
-
spotifywebapipython-1.0.
|
|
141
|
-
spotifywebapipython-1.0.
|
|
142
|
-
spotifywebapipython-1.0.
|
|
143
|
-
spotifywebapipython-1.0.
|
|
144
|
-
spotifywebapipython-1.0.
|
|
140
|
+
spotifywebapipython-1.0.293.dist-info/LICENSE,sha256=KGcc9g0zwqNLcWnSn_ezv1UtKyhMENFhvtixpxUPNsE,1177
|
|
141
|
+
spotifywebapipython-1.0.293.dist-info/METADATA,sha256=U63TtXsVnTIqv8ziG-gLeCbHLU70sHMVNWpP9Xur2ls,11644
|
|
142
|
+
spotifywebapipython-1.0.293.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
143
|
+
spotifywebapipython-1.0.293.dist-info/top_level.txt,sha256=jTBLFlijKTesYh2dteAz4vb17qjaqWKeDjpnnwTcrjs,20
|
|
144
|
+
spotifywebapipython-1.0.293.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{spotifywebapipython-1.0.291.dist-info → spotifywebapipython-1.0.293.dist-info}/top_level.txt
RENAMED
|
File without changes
|