spotifywebapipython.spotifyconnect.spotifyconnectdirectorytask

class SpotifyConnectDirectoryTask(threading.Thread):

Spotify Connect Directory thread task.

This class discovers available Spotify Connect devices on the local network. Discovered devices are then added to an internal list, which can be referenced by clients.

The directory task is started immediately after the authorization token is established in the SpotifyClient object.

SpotifyConnectDirectoryTask( spotifyClientInstance, zeroconfInstance: zeroconf._core.Zeroconf = None, initialDiscoveryTimeout: float = 3.0)

Initializes a new instance of the class.

Arguments:
  • spotifyClientInstance (SpotifyClient): SpotifyClient instance used to interface with the Spotify Web API.
  • zeroconfInstance (Zeroconf): Zeroconf instance used to query zeroconf; otherwise, None to create a new zeroconf instance.
  • initialDiscoveryTimeout (float): Time (in seconds) to give child Zeroconf discovery threads time to process initial Zeroconf service information changes. Default is 3.

The initialDiscoveryTimeout argument gives the child Zeroconf discovery threads time to process initial Zeroconf service information changes prior to setting the WaitForInitComplete event as complete. This gives the directory thread task time to discover all of the Spotify Connect devices currently attached to the local network.

name

A string used for identification purposes only.

It has no semantics. Multiple threads may be given the same name. The initial name is set by the constructor.

DeviceAdded

Event raised when a Spotify Connect device entry has been added.

DeviceRemoved

Event raised when a Spotify Connect device entry has been removed.

DeviceUpdated

Event raised when a Spotify Connect device entry has been updated.

WaitForInitComplete

Event that will be posted when the task has been initialized, and is waiting for commands or device notifications.

WaitForActivationComplete

Event that will be posted when the task has completed the activation sequence for the device, which is either a addUserResponse or addUserError notification.

WaitForTransferComplete

Event that will be posted when the task has completed the playback transfer sequence for the device, which is either a transferSuccess or transferError notification.

InitialDiscoveryTimeout: float

Time to wait (in seconds) after starting the Zeroconf discovery thread tasks before marking the directory task initialization as complete.

IsStopRequested: bool

Indicator used to denote the task has been asked to stop by the main thread.

Collection of SpotifyConnectZeroconfCastAppTask objects that have been created when transferring playback.

CastBrowser: pychromecast.discovery.CastBrowser

Returns the internal CastBrowser object.

IsZeroconDiscoveryEnabled: bool

Returns True if Zeroconf discovery is enabled; otherwise, False.

SpotifyClientInstance: object

Returns the SpotifyClient instance.

ZeroconfInstance: zeroconf._core.Zeroconf

Returns the zeroconf instance.

def run(self):

The task to perform on a seperate thread.

def ActivateCastAppSpotify( self, deviceName: str, transferPlayback: bool = False, timeoutActivation: float = 15.0, timeoutTransfer: float = 10.0) -> str:

Activates the Spotify Cast Application on the specified Chromecast device.

It will also call the OnCastGetInfoResponseReceived method when the Spotify Cast App receives a GetInfoResponse block that contains Spotify Connect Zeroconf GetInformation data about the device.

It will also call the OnCastZeroconfResponseReceived method when the Spotify Cast App receives any of the following message that contain zeroconf response data: addUserResponse, addUserError, transferError, transferSuccess.

Once activated, you have about 20 seconds to transfer playback to the device. The Spotify Cast application will automatically end after 20 seconds if playback is not transferred to it within the timeout period. Note that any application can be used to transfer playback to the device (Spotify Mobile / Desktop / Web, spotipy, spotifywebapipython, etc).

Arguments:
  • deviceName (str): Chromecast device friendly name (or device id) to activate.
  • transferPlayback (bool): True to transfer playback to the device; otherwise, False to just activate the Spotify Cast App on the device.
  • timeoutActivation (float): Amount of time to wait (in seconds) for the Spotify Cast App to be fully activated, the user logged in, and ready for transfer of playback.
    Default is 15 seconds.
  • timeoutTransfer (float): If transferPlayback argument is True, the amount of time to wait (in seconds) for the transfer to complete; otherwise, argument is ignored.
    Default is 10 seconds.
Returns:

The deviceId that was activated.

def AddDynamicDevice(self, device: spotifywebapipython.models.device.Device) -> None:

Adds a new dynamic SpotifyConnectDevice entry to the devices collection.

Arguments:
  • device (Device): Device information to add.

Dynamic devices are Spotify Connect devices that are not found in Zeroconf discovery process, but still exist in the player device list. These are usually Spotify Player client devices (e.g. mobile / web / desktop players) that utilize temporary device id's.

Sample Code

from spotifywebapipython import *
from spotifywebapipython.models import *

try:

    # this sample requires an authorization token, as it requires security scope to accesses user data.

    CLIENT_ID:str = 'your_client_id'
    SPOTIFY_SCOPES:list = \
    [
        'user-read-currently-playing',
        'user-read-playback-state',
        'user-read-email',
    ]

    # Spotify Connect credentials and timeout:
    spotifyConnectUsername:str = 'your_spotify_username'    # (e.g. "MyUserName@yahoo.com")
    spotifyConnectPassword:str = 'your_spotify_password'    # (e.g. "MyPassword")
    spotifyConnectLoginId:str  = 'your_spotify_loginid'     # (e.g. "31l88dfjhgnnhh44f7vjj67jdjfc")
    spotifyConnectDiscoveryTimeout:float = 4.0              # seconds

    # create new spotify client instance.
    spotify:SpotifyClient = SpotifyClient(
        tokenStorageDir='./test/testdata', 
        spotifyConnectUsername=spotifyConnectUsername, 
        spotifyConnectPassword=spotifyConnectPassword, 
        spotifyConnectLoginId=spotifyConnectLoginId,
        spotifyConnectDiscoveryTimeout=spotifyConnectDiscoveryTimeout
        )

    # generate a spotify authorization code with PKCE access token (with scope, private and public data use).
    spotify.SetAuthTokenAuthorizationCodePKCE(CLIENT_ID, SPOTIFY_SCOPES)
    print('\nAuth Token:\n Type="%s"\n Scope="%s"' % (spotify.AuthToken.AuthorizationType, str(spotify.AuthToken.Scope)))
    print('\nUser:\n DisplayName="%s"\n EMail="%s"' % (spotify.UserProfile.DisplayName, spotify.UserProfile.EMail))

    # log all spotify connect devices.
    scDevices = spotify.GetSpotifyConnectDevices(refresh=True)
    print('\nSpotify Connect device list (before) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

    # add dynamic device to Spotify Connect Devices collection.
    device:Device = Device()
    device.Id = "1234567890123456789012345678901234567890"
    device.Name = "MyNewDevice"
    device.Type = "SPEAKER"
    print('\nAdding new dynamic device: \"%s\" ...' % (device.Name))
    spotify.SpotifyConnectDirectory.AddDynamicDevice(device)

    # log all spotify connect devices.
    scDevices = spotify.GetSpotifyConnectDevices(refresh=False)
    print('\nSpotify Connect device list (after add) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

    # remove dynamic device from Spotify Connect Devices collection.
    print('\nRemoving existing dynamic device: \"%s\" ...' % (device.Name))
    spotify.SpotifyConnectDirectory.RemoveDevice(device.Id, dynamicDeviceOnly=True)

    # log all spotify connect devices.
    scDevices = spotify.GetSpotifyConnectDevices(refresh=False)
    print('\nSpotify Connect device list (after remove) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

except Exception as ex:

    print("** Exception: %s" % str(ex))

finally:

    # shut down zeroconf directory browser and dispose of all resources.
    if (spotify is not None):
        spotify.Dispose()

def GetActiveDevice( self, refresh: bool = False) -> spotifywebapipython.models.spotifyconnectdevice.SpotifyConnectDevice:

Returns the device currently marked as active if found; otherwise, null.

Arguments:
  • refresh (bool): True to retrieve active device from Spotify Web API player state; otherwise, False to retrieve active device from devices collection.
Returns:

The device currently marked as active if found; otherwise, null.

The object returned is a copy of the internal master device entry; any changes made to the copy do not affect the internal master device entry.

Sample Code

from spotifywebapipython import *
from spotifywebapipython.models import *

try:

    # this sample requires an authorization token, as it requires security scope to accesses user data.

    CLIENT_ID:str = 'your_client_id'
    SPOTIFY_SCOPES:list = \
    [
        'user-read-currently-playing',
        'user-read-playback-state',
        'user-read-email',
    ]

    # Spotify Connect credentials and timeout:
    spotifyConnectUsername:str = 'your_spotify_username'    # (e.g. "MyUserName@yahoo.com")
    spotifyConnectPassword:str = 'your_spotify_password'    # (e.g. "MyPassword")
    spotifyConnectLoginId:str  = 'your_spotify_loginid'     # (e.g. "31l88dfjhgnnhh44f7vjj67jdjfc")
    spotifyConnectDiscoveryTimeout:float = 4.0              # seconds

    # create new spotify client instance.
    spotify:SpotifyClient = SpotifyClient(
        tokenStorageDir='./test/testdata', 
        spotifyConnectUsername=spotifyConnectUsername, 
        spotifyConnectPassword=spotifyConnectPassword, 
        spotifyConnectLoginId=spotifyConnectLoginId,
        spotifyConnectDiscoveryTimeout=spotifyConnectDiscoveryTimeout
        )

    # generate a spotify authorization code with PKCE access token (with scope, private and public data use).
    spotify.SetAuthTokenAuthorizationCodePKCE(CLIENT_ID, SPOTIFY_SCOPES)
    print('\nAuth Token:\n Type="%s"\n Scope="%s"' % (spotify.AuthToken.AuthorizationType, str(spotify.AuthToken.Scope)))
    print('\nUser:\n DisplayName="%s"\n EMail="%s"' % (spotify.UserProfile.DisplayName, spotify.UserProfile.EMail))

    # get active device info.
    print('\nGetting active player device ...\n')
    scDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.GetActiveDevice()

    if scDevice is not None:
        print(str(scDevice))
    else:
        print("No active device")

except Exception as ex:

    print("** Exception: %s" % str(ex))

finally:

    # shut down zeroconf directory browser and dispose of all resources.
    if (spotify is not None):
        spotify.Dispose()

def GetDevice( self, value: str, refreshDynamicDevices: bool = True, raiseExceptionIfNotFound: bool = True) -> spotifywebapipython.models.spotifyconnectdevice.SpotifyConnectDevice:

Returns a SpotifyConnectDevice object for the specified device name / id if found in the devices collection. otherwise, returns the currently active player SpotifyConnectDevice object is returned. otherwise, null is returned.

Arguments:
  • value (str | None): The target player device identifier. This could be an id, name, a default device indicator (e.g. "*"), or null to utilize the active player device.
    Examples are 0d1841b0976bae2a3a310dd74c0f3df354899bc8, Office, *, None.
  • refreshDynamicDevices (bool): True to refresh the list of dynamically added devices and the active player state from real-time Spotify Web API data; otherwise, false to use the current cached state and device list. Default is True.
  • raiseExceptionIfNotFound (bool): True to raise an exception if a device could not be resolved; otherwise, False to just return a null value.
    Default is True.
Returns:

A SpotifyConnectDevice object for the specified device name / id if found; otherwise, null.

Raises:
  • SpotifyConnectDeviceNotFound: If the raiseExceptionIfNotFound argument value is True, and the specified device value was not found or there was no default device found.
  • SpotifyApiError: If an error occured while obtaining current Spotify Web API Player device data.

If a SpotifyConnectDevice object is returned, it will be a copy of the internal master device entry; any changes made to the copy do not affect the internal master device entry.

Sample Code

from spotifywebapipython import *
from spotifywebapipython.models import *

try:

    # this sample requires an authorization token, as it requires security scope to accesses user data.

    CLIENT_ID:str = 'your_client_id'
    SPOTIFY_SCOPES:list = \
    [
        'user-read-currently-playing',
        'user-read-playback-state',
        'user-read-email',
    ]

    # Spotify Connect credentials and timeout:
    spotifyConnectUsername:str = 'your_spotify_username'    # (e.g. "MyUserName@yahoo.com")
    spotifyConnectPassword:str = 'your_spotify_password'    # (e.g. "MyPassword")
    spotifyConnectLoginId:str  = 'your_spotify_loginid'     # (e.g. "31l88dfjhgnnhh44f7vjj67jdjfc")
    spotifyConnectDiscoveryTimeout:float = 4.0              # seconds

    # create new spotify client instance.
    spotify:SpotifyClient = SpotifyClient(
        tokenStorageDir='./test/testdata', 
        spotifyConnectUsername=spotifyConnectUsername, 
        spotifyConnectPassword=spotifyConnectPassword, 
        spotifyConnectLoginId=spotifyConnectLoginId,
        spotifyConnectDiscoveryTimeout=spotifyConnectDiscoveryTimeout
        )

    # generate a spotify authorization code with PKCE access token (with scope, private and public data use).
    spotify.SetAuthTokenAuthorizationCodePKCE(CLIENT_ID, SPOTIFY_SCOPES)
    print('\nAuth Token:\n Type="%s"\n Scope="%s"' % (spotify.AuthToken.AuthorizationType, str(spotify.AuthToken.Scope)))
    print('\nUser:\n DisplayName="%s"\n EMail="%s"' % (spotify.UserProfile.DisplayName, spotify.UserProfile.EMail))

    # get device info - by name.
    # exception will be raised if device was not resolved.
    device:str = "Bose-ST10-2"
    print("\nDevice info - by name \"%s\" ..." % (device))
    scDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.GetDevice(device)
    print(str(scDevice) + "\n")

    # get device info - by id.
    # exception will be raised if device was not resolved.
    device:str = "5d4931f9d0684b625d702eaa24137b2c1d99539c"
    print("\nDevice info - by id \"%s\" ..." % (device))
    scDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.GetDevice(device)
    print(str(scDevice) + "\n")

    # get device info - by * default.
    # exception will be raised if device was not resolved.
    spotify.DefaultDeviceId = "Bose-ST10-1111"
    device:str = "*"
    print("\nDevice info - by * default  \"%s\" ..." % (device))
    scDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.GetDevice(device)
    print(str(scDevice) + "\n")

    # get device info - by default.
    # exception will be raised if device was not resolved.
    device:str = None
    print("\nDevice info - by active default  \"%s\" ..." % (device))
    scDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.GetDevice(device)
    print(str(scDevice) + "\n")

except Exception as ex:

    print("** Exception: %s" % str(ex))

finally:

    # shut down zeroconf directory browser and dispose of all resources.
    if (spotify is not None):
        spotify.Dispose()

Returns a collection of available Spotify Connect devices.

The object returned is a copy of the internal master device list; any changes made to the copy do not affect the internal master device list.

Sample Code

from spotifywebapipython import *
from spotifywebapipython.models import *

try:

    # this sample requires an authorization token, as it requires security scope to accesses user data.

    CLIENT_ID:str = 'your_client_id'
    SPOTIFY_SCOPES:list = \
    [
        'user-read-currently-playing',
        'user-read-playback-state',
        'user-read-email',
    ]

    # Spotify Connect credentials and timeout:
    spotifyConnectUsername:str = 'your_spotify_username'    # (e.g. "MyUserName@yahoo.com")
    spotifyConnectPassword:str = 'your_spotify_password'    # (e.g. "MyPassword")
    spotifyConnectLoginId:str  = 'your_spotify_loginid'     # (e.g. "31l88dfjhgnnhh44f7vjj67jdjfc")
    spotifyConnectDiscoveryTimeout:float = 4.0              # seconds

    # create new spotify client instance.
    spotify:SpotifyClient = SpotifyClient(
        tokenStorageDir='./test/testdata', 
        spotifyConnectUsername=spotifyConnectUsername, 
        spotifyConnectPassword=spotifyConnectPassword, 
        spotifyConnectLoginId=spotifyConnectLoginId,
        spotifyConnectDiscoveryTimeout=spotifyConnectDiscoveryTimeout
        )

    # generate a spotify authorization code with PKCE access token (with scope, private and public data use).
    spotify.SetAuthTokenAuthorizationCodePKCE(CLIENT_ID, SPOTIFY_SCOPES)
    print('\nAuth Token:\n Type="%s"\n Scope="%s"' % (spotify.AuthToken.AuthorizationType, str(spotify.AuthToken.Scope)))
    print('\nUser:\n DisplayName="%s"\n EMail="%s"' % (spotify.UserProfile.DisplayName, spotify.UserProfile.EMail))

    # get devices from Spotify Connect Directory task.
    # note that collection is already sorted as devices are added.
    scDevices:SpotifyConnectDevices = spotify.SpotifyConnectDirectory.GetDevices()

    # log all spotify connect devices.
    print('\nSpotify Connect device list (after) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

except Exception as ex:

    print("** Exception: %s" % str(ex))

finally:

    # shut down zeroconf directory browser and dispose of all resources.
    if (spotify is not None):
        spotify.Dispose()

def GetPlayerDevice( self, value: str, refresh: bool = False) -> spotifywebapipython.models.spotifyconnectdevice.SpotifyConnectDevice:

Returns the device instance if it is currently in the Spotify Web API player device list; otherwise, null.

Arguments:
  • value (str): Spotify Connect device name or id value used to identify the device.
  • refresh (bool): True to refresh player devices from Spotify Web API devices; otherwise, False to retrieve player device from devices collection.
Returns:

The device instance if it is currently in the Spotify Web API player device list; otherwise, null.

The object returned is a copy of the internal master device entry; any changes made to the copy do not affect the internal master device entry.

Sample Code

from spotifywebapipython import *
from spotifywebapipython.models import *

try:

    # this sample requires an authorization token, as it requires security scope to accesses user data.

    CLIENT_ID:str = 'your_client_id'
    SPOTIFY_SCOPES:list = \
    [
        'user-read-currently-playing',
        'user-read-playback-state',
        'user-read-email',
    ]

    # Spotify Connect credentials and timeout:
    spotifyConnectUsername:str = 'your_spotify_username'    # (e.g. "MyUserName@yahoo.com")
    spotifyConnectPassword:str = 'your_spotify_password'    # (e.g. "MyPassword")
    spotifyConnectLoginId:str  = 'your_spotify_loginid'     # (e.g. "31l88dfjhgnnhh44f7vjj67jdjfc")
    spotifyConnectDiscoveryTimeout:float = 4.0              # seconds

    # create new spotify client instance.
    spotify:SpotifyClient = SpotifyClient(
        tokenStorageDir='./test/testdata', 
        spotifyConnectUsername=spotifyConnectUsername, 
        spotifyConnectPassword=spotifyConnectPassword, 
        spotifyConnectLoginId=spotifyConnectLoginId,
        spotifyConnectDiscoveryTimeout=spotifyConnectDiscoveryTimeout
        )

    # generate a spotify authorization code with PKCE access token (with scope, private and public data use).
    spotify.SetAuthTokenAuthorizationCodePKCE(CLIENT_ID, SPOTIFY_SCOPES)
    print('\nAuth Token:\n Type="%s"\n Scope="%s"' % (spotify.AuthToken.AuthorizationType, str(spotify.AuthToken.Scope)))
    print('\nUser:\n DisplayName="%s"\n EMail="%s"' % (spotify.UserProfile.DisplayName, spotify.UserProfile.EMail))

    # get player device info - by name.
    device:str = "Bose-ST10-1"
    print("\nPlayer device info - by name \"%s\" ..." % (device))
    scDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.GetPlayerDevice(device, refresh=True)
    if scDevice is not None:
        print(str(scDevice) + "\n")
    else:
        print("Player device not found: \"%s\"" % (device))

    # get player device info - by id.
    device:str = "30fbc80e35598f3c242f2120413c943dfd9715fe"
    print("\nPlayer device info - by id \"%s\" ..." % (device))
    scDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.GetPlayerDevice(device, refresh=True)
    if scDevice is not None:
        print(str(scDevice) + "\n")
    else:
        print("Player device not found: \"%s\"" % (device))

    # get player device info - by unknown name.
    device:str = "MyName"
    print("\nPlayer device info - by unknown name \"%s\" ..." % (device))
    scDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.GetPlayerDevice(device, refresh=True)
    if scDevice is not None:
        print(str(scDevice) + "\n")
    else:
        print("Player device not found: \"%s\"" % (device))

except Exception as ex:

    print("** Exception: %s" % str(ex))

finally:

    # shut down zeroconf directory browser and dispose of all resources.
    if (spotify is not None):
        spotify.Dispose()

def GetSonosPlayer( self, device: spotifywebapipython.models.spotifyconnectdevice.SpotifyConnectDevice, returnCoordinator: bool = True) -> soco.core.SoCo:

Returns the Sonos Controller instance for the specified Spotify Connect device. Returns the Sonos player instance for the specified Spotify Connect Sonos device.

Arguments:
  • device (SpotifyConnectDevice): Spotify Connect device instance used to identify the Sonos player.
  • returnCoordinator (bool): True to return the group coordinator instance if the device is part of a Sonos group; otherwise, False to return the found instance;
    Default is True.
Returns:

The Sonos Controller instance for the specified Spotify Connect device.

Raises:
  • SpotifyApiError: If a Sonos Controller instance could not be found for the device id.

You should invoke "if (scDevice.IsSonos):" logic prior to calling this method, as a Sonos Controller instance will not be created for non-Sonos devices and an exception will be raised!

def GetSpotifyDeviceIDFromName(self, name: str) -> str:

Retrieve the Spotify deviceID from provided user-friendly name.

DeviceId is just the md5 hash representation of the user-friendly-name.

Refreshes dynamic Spotify Connect devices, and also determines the currently active device (if any).

Returns:

A SpotifyConnectDevice object that contains the active device if one was found; otherwise, null to indicate no active device.

Dynamic devices are Spotify Connect devices that are not found in Zeroconf discovery process, but exist in the player device list. These are usually Spotify Connect web or mobile players with temporary device id's.

The object returned is a copy of the internal master device entry; any changes made to the copy do not affect the internal master device entry.

Sample Code

from spotifywebapipython import *
from spotifywebapipython.models import *

try:

    # this sample requires an authorization token, as it requires security scope to accesses user data.

    CLIENT_ID:str = 'your_client_id'
    SPOTIFY_SCOPES:list = \
    [
        'user-read-currently-playing',
        'user-read-playback-state',
        'user-read-email',
    ]

    # Spotify Connect credentials and timeout:
    spotifyConnectUsername:str = 'your_spotify_username'    # (e.g. "MyUserName@yahoo.com")
    spotifyConnectPassword:str = 'your_spotify_password'    # (e.g. "MyPassword")
    spotifyConnectLoginId:str  = 'your_spotify_loginid'     # (e.g. "31l88dfjhgnnhh44f7vjj67jdjfc")
    spotifyConnectDiscoveryTimeout:float = 4.0              # seconds

    # create new spotify client instance.
    spotify:SpotifyClient = SpotifyClient(
        tokenStorageDir='./test/testdata', 
        spotifyConnectUsername=spotifyConnectUsername, 
        spotifyConnectPassword=spotifyConnectPassword, 
        spotifyConnectLoginId=spotifyConnectLoginId,
        spotifyConnectDiscoveryTimeout=spotifyConnectDiscoveryTimeout
        )

    # generate a spotify authorization code with PKCE access token (with scope, private and public data use).
    spotify.SetAuthTokenAuthorizationCodePKCE(CLIENT_ID, SPOTIFY_SCOPES)
    print('\nAuth Token:\n Type="%s"\n Scope="%s"' % (spotify.AuthToken.AuthorizationType, str(spotify.AuthToken.Scope)))
    print('\nUser:\n DisplayName="%s"\n EMail="%s"' % (spotify.UserProfile.DisplayName, spotify.UserProfile.EMail))

    # log all spotify connect devices.
    scDevices = spotify.GetSpotifyConnectDevices(refresh=True)
    print('\nSpotify Connect device list (before) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

    # refresh the player device list, and return the active device.
    scActiveDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.RefreshDynamicDevices()

    # log all spotify connect devices.
    scDevices = spotify.GetSpotifyConnectDevices(refresh=True)
    print('\nSpotify Connect device list (after) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

except Exception as ex:

    print("** Exception: %s" % str(ex))

finally:

    # shut down zeroconf directory browser and dispose of all resources.
    if (spotify is not None):
        spotify.Dispose()

def RemoveDevice( self, deviceId: str, dynamicDeviceOnly: bool = False) -> spotifywebapipython.models.spotifyconnectdevice.SpotifyConnectDevice:

Removes existing device entry(s) from the devices collection by device id value.

Arguments:
  • deviceId (str): Device id to remove.
  • dynamicDeviceOnly (str): True to only remove the device if it's a dynamic device entry; otherwise, False to remove the device id regardless.
    Default is False.
Returns:

A SpotifyConnectDevice object that contains the removed device if one was found; otherwise, null to indicate no device was removed.

It's possible to have multiple devices with the same id (e.g. both a dynamic and a zeroconf registered device).

Dynamic devices are Spotify Connect devices that are not found in Zeroconf discovery process, but still exist in the player device list. These are usually Spotify Player client devices (e.g. mobile / web / desktop players) that utilize temporary device id's.

The object returned is a copy of the internal master device entry; any changes made to the copy do not affect the internal master device entry.

Sample Code

from spotifywebapipython import *
from spotifywebapipython.models import *

try:

    # this sample requires an authorization token, as it requires security scope to accesses user data.

    CLIENT_ID:str = 'your_client_id'
    SPOTIFY_SCOPES:list = \
    [
        'user-read-currently-playing',
        'user-read-playback-state',
        'user-read-email',
    ]

    # Spotify Connect credentials and timeout:
    spotifyConnectUsername:str = 'your_spotify_username'    # (e.g. "MyUserName@yahoo.com")
    spotifyConnectPassword:str = 'your_spotify_password'    # (e.g. "MyPassword")
    spotifyConnectLoginId:str  = 'your_spotify_loginid'     # (e.g. "31l88dfjhgnnhh44f7vjj67jdjfc")
    spotifyConnectDiscoveryTimeout:float = 4.0              # seconds

    # create new spotify client instance.
    spotify:SpotifyClient = SpotifyClient(
        tokenStorageDir='./test/testdata', 
        spotifyConnectUsername=spotifyConnectUsername, 
        spotifyConnectPassword=spotifyConnectPassword, 
        spotifyConnectLoginId=spotifyConnectLoginId,
        spotifyConnectDiscoveryTimeout=spotifyConnectDiscoveryTimeout
        )

    # generate a spotify authorization code with PKCE access token (with scope, private and public data use).
    spotify.SetAuthTokenAuthorizationCodePKCE(CLIENT_ID, SPOTIFY_SCOPES)
    print('\nAuth Token:\n Type="%s"\n Scope="%s"' % (spotify.AuthToken.AuthorizationType, str(spotify.AuthToken.Scope)))
    print('\nUser:\n DisplayName="%s"\n EMail="%s"' % (spotify.UserProfile.DisplayName, spotify.UserProfile.EMail))

    # log all spotify connect devices.
    scDevices = spotify.GetSpotifyConnectDevices(refresh=True)
    print('\nSpotify Connect device list (before) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

    # add dynamic device to Spotify Connect Devices collection.
    device:Device = Device()
    device.Id = "1234567890123456789012345678901234567890"
    device.Name = "MyNewDevice"
    device.Type = "SPEAKER"
    print('\nAdding new dynamic device: \"%s\" ...' % (device.Name))
    spotify.SpotifyConnectDirectory.AddDynamicDevice(device)

    # log all spotify connect devices.
    scDevices = spotify.GetSpotifyConnectDevices(refresh=False)
    print('\nSpotify Connect device list (after add) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

    # remove dynamic device from Spotify Connect Devices collection.
    print('\nRemoving existing dynamic device: \"%s\" ...' % (device.Name))
    spotify.SpotifyConnectDirectory.RemoveDevice(device.Id, dynamicDeviceOnly=True)

    # log all spotify connect devices.
    scDevices = spotify.GetSpotifyConnectDevices(refresh=False)
    print('\nSpotify Connect device list (after remove) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

except Exception as ex:

    print("** Exception: %s" % str(ex))

finally:

    # shut down zeroconf directory browser and dispose of all resources.
    if (spotify is not None):
        spotify.Dispose()

def UpdatePlayerDevices( self, playerDevices: list[spotifywebapipython.models.device.Device] = None) -> None:

Adds a list of dynamic player device entries to the devices collection, and removes any existing dynamic devices from the collection that are not in the playerDevices list.

Arguments:
  • playerDevices (list[Device]): If specified, the list of current player devices obtained via a previous call to the Spotify Web API; otherwise, null to call the Spotify Web API to retrieve the list.

Dynamic devices are Spotify Connect devices that are not found in Zeroconf discovery process, but still exist in the player device list. These are usually Spotify Player client devices (e.g. mobile / web / desktop players) that utilize temporary device id's.

Sample Code

from spotifywebapipython import *
from spotifywebapipython.models import *

try:

    # this sample requires an authorization token, as it requires security scope to accesses user data.

    CLIENT_ID:str = 'your_client_id'
    SPOTIFY_SCOPES:list = \
    [
        'user-read-currently-playing',
        'user-read-playback-state',
        'user-read-email',
    ]

    # Spotify Connect credentials and timeout:
    spotifyConnectUsername:str = 'your_spotify_username'    # (e.g. "MyUserName@yahoo.com")
    spotifyConnectPassword:str = 'your_spotify_password'    # (e.g. "MyPassword")
    spotifyConnectLoginId:str  = 'your_spotify_loginid'     # (e.g. "31l88dfjhgnnhh44f7vjj67jdjfc")
    spotifyConnectDiscoveryTimeout:float = 4.0              # seconds

    # create new spotify client instance.
    spotify:SpotifyClient = SpotifyClient(
        tokenStorageDir='./test/testdata', 
        spotifyConnectUsername=spotifyConnectUsername, 
        spotifyConnectPassword=spotifyConnectPassword, 
        spotifyConnectLoginId=spotifyConnectLoginId,
        spotifyConnectDiscoveryTimeout=spotifyConnectDiscoveryTimeout
        )

    # generate a spotify authorization code with PKCE access token (with scope, private and public data use).
    spotify.SetAuthTokenAuthorizationCodePKCE(CLIENT_ID, SPOTIFY_SCOPES)
    print('\nAuth Token:\n Type="%s"\n Scope="%s"' % (spotify.AuthToken.AuthorizationType, str(spotify.AuthToken.Scope)))
    print('\nUser:\n DisplayName="%s"\n EMail="%s"' % (spotify.UserProfile.DisplayName, spotify.UserProfile.EMail))

    # log all spotify connect devices.
    scDevices = spotify.GetSpotifyConnectDevices(refresh=True)
    print('\nSpotify Connect device list (before) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

    # update player device list.
    spotify.SpotifyConnectDirectory.UpdatePlayerDevices()

    # log all spotify connect devices.
    scDevices = spotify.GetSpotifyConnectDevices(refresh=False)
    print('\nSpotify Connect device list (after) ...')
    scDevice:SpotifyConnectDevice
    for idx in range(len(scDevices)):
        scDevice:SpotifyConnectDevice = scDevices[idx]
        isActive:str = " (active)" if (scDevice.IsActiveDevice) else ""
        print("%s - %s [%s]%s" % (str(idx), scDevice.Title, scDevice.DiscoveryResult.Description, isActive))

except Exception as ex:

    print("** Exception: %s" % str(ex))

finally:

    # shut down zeroconf directory browser and dispose of all resources.
    if (spotify is not None):
        spotify.Dispose()

Updates the currently active device based on playerState.

Arguments:
  • playerState (PlayerPlayState): Current player state obtained via a call to GetPlayerPlaybackState method which will be used to set the active device in the Items collection; otherwise, null to bypass active device set.
Returns:

The currently active Spotify Player device instance if one was found; otherwise, null.

The Spotify Web API GetPlayerPlaybackState method is called to retrieve the active device information.

The object returned is a copy of the internal master device entry; any changes made to the copy do not affect the internal master device entry.

Sample Code

from spotifywebapipython import *
from spotifywebapipython.models import *

try:

    # this sample requires an authorization token, as it requires security scope to accesses user data.

    CLIENT_ID:str = 'your_client_id'
    SPOTIFY_SCOPES:list = \
    [
        'user-read-currently-playing',
        'user-read-playback-state',
        'user-read-email',
    ]

    # Spotify Connect credentials and timeout:
    spotifyConnectUsername:str = 'your_spotify_username'    # (e.g. "MyUserName@yahoo.com")
    spotifyConnectPassword:str = 'your_spotify_password'    # (e.g. "MyPassword")
    spotifyConnectLoginId:str  = 'your_spotify_loginid'     # (e.g. "31l88dfjhgnnhh44f7vjj67jdjfc")
    spotifyConnectDiscoveryTimeout:float = 4.0              # seconds

    # create new spotify client instance.
    spotify:SpotifyClient = SpotifyClient(
        tokenStorageDir='./test/testdata', 
        spotifyConnectUsername=spotifyConnectUsername, 
        spotifyConnectPassword=spotifyConnectPassword, 
        spotifyConnectLoginId=spotifyConnectLoginId,
        spotifyConnectDiscoveryTimeout=spotifyConnectDiscoveryTimeout
        )

    # generate a spotify authorization code with PKCE access token (with scope, private and public data use).
    spotify.SetAuthTokenAuthorizationCodePKCE(CLIENT_ID, SPOTIFY_SCOPES)
    print('\nAuth Token:\n Type="%s"\n Scope="%s"' % (spotify.AuthToken.AuthorizationType, str(spotify.AuthToken.Scope)))
    print('\nUser:\n DisplayName="%s"\n EMail="%s"' % (spotify.UserProfile.DisplayName, spotify.UserProfile.EMail))

    # log active device info.
    print('\nGetting active player device (before) ...\n')
    scDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.GetActiveDevice()
    if scDevice is not None:
        print(str(scDevice))
    else:
        print("No active device")

    # updates currently active device based on current playerState.
    scActiveDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.UpdateActiveDevice()

    # updates currently active device based on specified playerState.
    playerState:PlayerPlayState = spotify.GetPlayerPlaybackState(additionalTypes='episode')
    scActiveDevice:SpotifyConnectDevice = spotify.SpotifyConnectDirectory.UpdateActiveDevice(playerState)

    # log active device info.
    print('\nActive player device (after) ...\n')
    if scActiveDevice is not None:
        print(str(scActiveDevice))
    else:
        print("No active device")

except Exception as ex:

    print("** Exception: %s" % str(ex))

finally:

    # shut down zeroconf directory browser and dispose of all resources.
    if (spotify is not None):
        spotify.Dispose()

def OnServiceInfoAddedUpdatedChromecast( self, zeroconfDiscoveryResult: spotifywebapipython.models.zeroconfdiscoveryresult.ZeroconfDiscoveryResult, uuid: uuid.UUID, serviceName: str, serviceType: str) -> None:

Called when a Chromecast MDNS service record has been discovered or updated for a Chromecast device.

Arguments:
  • zeroconfDiscoveryResult (ZeroconfDiscoveryResult): A ZeroconfDiscoveryResult object that contains discovery details.
  • uuid (UUID): The cast's uuid, which is the dictionary key to find the chromecast metadata in CastBrowser.devices and CastBrowser.services collection.
  • serviceName (str): First known MDNS service name or host:port.
  • serviceType (str): Service call type (e.g. "add_cast", "update_cast").

This method will be called in a thread-safe manner, as the caller is using the _Zeroconf_RLock object to control access.

def OnServiceInfoRemovedChromecast( self, zeroconfDiscoveryResult: spotifywebapipython.models.zeroconfdiscoveryresult.ZeroconfDiscoveryResult, uuid: uuid.UUID, serviceName: str, castInfo: pychromecast.models.CastInfo) -> None:

Called when a cast has been lost (MDNS info expired or host down).

Arguments:
  • zeroconfDiscoveryResult (ZeroconfDiscoveryResult): A ZeroconfDiscoveryResult object that contains discovery details.
  • uuid (UUID): The cast's uuid, which is the dictionary key to find the chromecast metadata in CastBrowser.devices collection.
  • serviceName (str): Last valid MDNS service name or host:port.
  • castInfo (CastInfo): CastInfo for the service to aid cleanup.

This could be called under the following conditions:

  • when a Chromecast device has logged out of zeroconf and left the network.
  • transfer playback failed (e.g. device restriction, etc).

This method will be called in a thread-safe manner, as the caller is using the _Zeroconf_RLock object to control access.

def OnCastGetInfoResponseReceived( self, uuid: uuid.UUID, info: spotifywebapipython.zeroconfapi.zeroconfgetinfo.ZeroconfGetInfo) -> None:

Called when the cast app task has received a Spotify Connect Zeroconf GetInfoResponse data structure.

Arguments:
  • uuid (UUID): Spotify Connect device that was added.
  • info (ZeroconfGetInfo): A ZeroconfGetInfo instance that contains the GetInfoResponse data.

This method allows us to update the SpotifyConnectDevice entry with the Spotify Connect Zeroconf device information.

def OnCastZeroconfResponseReceived( self, uuid: uuid.UUID, response: spotifywebapipython.zeroconfapi.zeroconfresponse.ZeroconfResponse) -> None:

Called when the cast app task has received a Spotify Connect ZeroconfResponse data structure.

Arguments:
  • uuid (UUID): Spotify Connect device that was added.
  • response (ZeroconfResponse): A ZeroconfResponse instance that contains the zeroconf response data.

This method allows us to update the SpotifyConnectDevice entry with the Spotify Connect Zeroconf response information.

def OnServiceInfoAddedUpdatedSpotifyConnect( self, zeroconfDiscoveryResult: spotifywebapipython.models.zeroconfdiscoveryresult.ZeroconfDiscoveryResult) -> None:

Called when a new Spotify Connect ServiceInfo record has been discovered or updated for a Spotify Connect device.

Arguments:
  • zeroconfDiscoveryResult (ZeroconfDiscoveryResult): A ZeroconfDiscoveryResult object that contains discovery details.

This method will be called in a thread-safe manner, as the caller is using the _Zeroconf_RLock object to control access.

def OnServiceInfoRemovedSpotifyConnect( self, zeroconfDiscoveryResult: spotifywebapipython.models.zeroconfdiscoveryresult.ZeroconfDiscoveryResult) -> None:

Called when an mDNS service is lost.

Arguments:
  • zeroconfDiscoveryResult (ZeroconfDiscoveryResult): A ZeroconfDiscoveryResult object that contains discovery details.

This method will be called in a thread-safe manner, as the caller is using the _Zeroconf_RLock object to control access.

@abstractmethod
def OnDeviceAdded( self, sender: object, e: spotifywebapipython.spotifyconnect.spotifyconnectdeviceeventargs.SpotifyConnectDeviceEventArgs) -> None:

Method that will handle the DeviceAdded event. Inheriting classes can override this method to handle the event.

Arguments:
  • sender (object): The object which fired the event.
  • e (SpotifyConnectDeviceEventArgs): Arguments that contain detailed information related to the event.

This event is fired when a Spotify Connect device has been added to the SpotifyConnectDevices collection.

This method will be called in a thread-safe manner, as the caller is using the SpotifyConnectDevices_RLock object to control access.

@abstractmethod
def OnDeviceRemoved( self, sender: object, e: spotifywebapipython.spotifyconnect.spotifyconnectdeviceeventargs.SpotifyConnectDeviceEventArgs) -> None:

Method that will handle the DeviceRemoved event. Inheriting classes can override this method to handle the event.

Arguments:
  • sender (object): The object which fired the event.
  • e (SpotifyConnectDeviceEventArgs): Arguments that contain detailed information related to the event.

This event is fired when a Spotify Connect device has been removed from the SpotifyConnectDevices collection.

This method will be called in a thread-safe manner, as the caller is using the SpotifyConnectDevices_RLock object to control access.

@abstractmethod
def OnDeviceUpdated( self, sender: object, e: spotifywebapipython.spotifyconnect.spotifyconnectdeviceeventargs.SpotifyConnectDeviceEventArgs) -> None:

Method that will handle the DeviceUpdated event. Inheriting classes can override this method to handle the event.

Arguments:
  • sender (object): The object which fired the event.
  • e (SpotifyConnectDeviceEventArgs): Arguments that contain detailed information related to the event.

This event is fired when a Spotify Connect device has been updated in the SpotifyConnectDevices collection.

This method will be called in a thread-safe manner, as the caller is using the SpotifyConnectDevices_RLock object to control access.