From 3aa0d8a1e6b811508becabebddcb8df1db490e71 Mon Sep 17 00:00:00 2001 From: Todd Lucas Date: Fri, 6 Dec 2024 12:50:13 -0600 Subject: [PATCH] [ 1.0.68 ] * Updated service `player_transfer_playback` to resume play if `play=True` and `force_activate_device=True`. If forcefully activating a device, then we need to resume play manually if `play=True` was specified; this is due to the device losing its current status since it was being forcefully activated (e.g. disconnected and reconnected). * Updated underlying `spotifywebapiPython` package requirement to version 1.0.123. --- CHANGELOG.md | 9 +++++-- custom_components/spotifyplus/manifest.json | 4 ++-- custom_components/spotifyplus/media_player.py | 24 +++++++++++++++---- requirements.txt | 2 +- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11b5596..ef400c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,16 @@ Change are listed in reverse chronological order (newest to oldest). +###### [ 1.0.68 ] - 2024/12/06 + + * Updated service `player_transfer_playback` to resume play if `play=True` and `force_activate_device=True`. If forcefully activating a device, then we need to resume play manually if `play=True` was specified; this is due to the device losing its current status since it was being forcefully activated (e.g. disconnected and reconnected). + * Updated underlying `spotifywebapiPython` package requirement to version 1.0.123. + ###### [ 1.0.67 ] - 2024/12/02 - * Updated underlying `spotifywebapiPython` package requirement to version 1.0.22. + * Updated underlying `spotifywebapiPython` package requirement to version 1.0.122. * The above `spotifywebapiPython` package will now return an exception due to the functions being deprecated by the Spotify development team. More information can be found on the [Spotify Developer Forum Blog post](https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api) that was conveyed on November 27, 2024. The following methods will now raise a `SpotifyApiError` exception due to the Spotify development team changes: `GetArtistRelatedArtists`, `GetTrackRecommendations`, `GetTrackAudioFeatures`, `GetFeaturedPlaylists`, `GetCategoryPlaylists`, `GetGenres`. The following properties were also marked as deprecated for the same reason: `TrackSimplified.PreviewUrl`. - * Due to the above chnages made by Spotify, any Algorithmic and Spotify-owned editorial playlists are no longer accessible or have more limited functionality. This means that you can no longer obtain details via the `SpotifyClient.GetPlaylist` and `SpotifyClient.GetPlaylistItems` methods for Spotify-owned / generated content (e.g. "Made For You", etc). A `404 - Not Found` error will be returned when trying to retrieve information for these playlist types. + * Due to the above changes made by Spotify, any Algorithmic and Spotify-owned editorial playlists are no longer accessible or have more limited functionality. This means that you can no longer obtain details via the `SpotifyClient.GetPlaylist` and `SpotifyClient.GetPlaylistItems` methods for Spotify-owned / generated content (e.g. "Made For You", etc). A `404 - Not Found` error will be returned when trying to retrieve information for these playlist types. ###### [ 1.0.66 ] - 2024/11/20 diff --git a/custom_components/spotifyplus/manifest.json b/custom_components/spotifyplus/manifest.json index 5cda2cd..24b2a75 100644 --- a/custom_components/spotifyplus/manifest.json +++ b/custom_components/spotifyplus/manifest.json @@ -18,10 +18,10 @@ "requests_oauthlib>=1.3.1", "soco>=0.30.4", "smartinspectPython>=3.0.33", - "spotifywebapiPython>=1.0.122", + "spotifywebapiPython>=1.0.123", "urllib3>=1.21.1,<1.27", "zeroconf>=0.132.2" ], - "version": "1.0.67", + "version": "1.0.68", "zeroconf": [ "_spotify-connect._tcp.local." ] } diff --git a/custom_components/spotifyplus/media_player.py b/custom_components/spotifyplus/media_player.py index ca761a3..64f8908 100644 --- a/custom_components/spotifyplus/media_player.py +++ b/custom_components/spotifyplus/media_player.py @@ -663,6 +663,7 @@ def media_play(self) -> None: else: # call Spotify Web API to process the request. + _logsi.LogVerbose("'%s': Issuing command to Spotify Player: PLAY" % (self.name)) self.data.spotifyClient.PlayerMediaResume() @@ -688,6 +689,7 @@ def media_pause(self) -> None: else: # call Spotify Web API to process the request. + _logsi.LogVerbose("'%s': Issuing command to Spotify Player: PAUSE" % (self.name)) self.data.spotifyClient.PlayerMediaPause() @@ -709,6 +711,7 @@ def media_previous_track(self) -> None: else: # call Spotify Web API to process the request. + _logsi.LogVerbose("'%s': Issuing command to Spotify Player: PREVIOUS" % (self.name)) self.data.spotifyClient.PlayerMediaSkipPrevious() @@ -730,6 +733,7 @@ def media_next_track(self) -> None: else: # call Spotify Web API to process the request. + _logsi.LogVerbose("'%s': Issuing command to Spotify Player: NEXT" % (self.name)) self.data.spotifyClient.PlayerMediaSkipNext() @@ -757,6 +761,7 @@ def media_seek(self, position: float) -> None: else: # call Spotify Web API to process the request. + _logsi.LogVerbose("'%s': Issuing command to Spotify Player: SEEK (position=%s)" % (self.name, position)) self.data.spotifyClient.PlayerMediaSeek(int(position * 1000)) @@ -892,7 +897,8 @@ def select_source(self, source: str) -> None: # transfer playback to the specified source. self.service_spotify_player_transfer_playback( source, - (self._attr_state != MediaPlayerState.PAUSED), + #play=(self._attr_state != MediaPlayerState.PAUSED), + play=True, refreshDeviceList=True, forceActivateDevice=True) @@ -1100,7 +1106,7 @@ def turn_on(self) -> None: self._playerState, self._spotifyConnectDevice, self._sonosDevice = self._GetPlayerPlaybackState() # update the source list (spotify connect devices cache). - self.data.spotifyClient.GetSpotifyConnectDevices(refresh=True) + #self.data.spotifyClient.GetSpotifyConnectDevices(refresh=True) # try to automatically select a source for play. # if spotify web api player is not found and a default spotify connect device is configured, then select it; @@ -1120,10 +1126,14 @@ def turn_on(self) -> None: else: _logsi.LogVerbose("'%s': Could not auto-select a source for play" % (self.name)) - # activate the selected source. + # was a source selected? if source is not None: + # yes - activate the selected source (e.g. transfer playback). self.select_source(source) self._isInCommandEvent = True # turn "in a command event" indicator back on. + else: + # no - update the source list (spotify connect devices cache). + self.data.spotifyClient.GetSpotifyConnectDevices(refresh=True) # is playing content paused? if so, then resume play. if (self._playerState.Device.IsActive) \ @@ -1661,7 +1671,7 @@ def _UpdateHAFromPlayerPlayState(self, playerPlayState:PlayerPlayState) -> None: self.data.spotifyClient.DefaultDeviceId = self._attr_source # check to see if currently active device is in the Spotify Connect device list cache. - # if it's not in the cache, then we need to refresh the Spotify Connect device list cache + # if it's not in the cache, then we need to refresh the Spotify Connect device list cache. scDevices:SpotifyConnectDevices = self.data.spotifyClient.GetSpotifyConnectDevices(refresh=False) if not scDevices.ContainsDeviceName(playerPlayState.Device.Name): _logsi.LogVerbose("'%s': Spotify PlayerPlayState device name '%s' was not found in the Spotify Connect device list cache; refreshing cache" % (self.name, self._attr_source)) @@ -7021,6 +7031,7 @@ def service_spotify_player_transfer_playback( apiMethodParms.AppendKeyValue("play", play) apiMethodParms.AppendKeyValue("delay", delay) apiMethodParms.AppendKeyValue("refreshDeviceList", refreshDeviceList) + apiMethodParms.AppendKeyValue("forceActivateDevice", forceActivateDevice) _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Player Transfer Playback Service", apiMethodParms) # validations. @@ -7233,6 +7244,11 @@ def service_spotify_player_transfer_playback( if scDevice is not None: self._attr_source = scDevice.Name _logsi.LogVerbose("'%s': Selected source was changed to: '%s'" % (self.name, self._attr_source)) + + # resume play (if requested and necessary). + if (play) and (self.state == 'paused'): + _logsi.LogVerbose("'%s': Selected source was changed to: '%s'" % (self.name, self._attr_source)) + self.media_play() # media player command was processed, so force a scan window at the next interval. _logsi.LogVerbose("'%s': Processed a transfer playback command - forcing a playerState scan window for the next %d updates" % (self.name, SPOTIFY_SCAN_INTERVAL_COMMAND - 1)) diff --git a/requirements.txt b/requirements.txt index d89dd54..3608730 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,4 @@ homeassistant==2024.5.0 ruff==0.1.3 soco>=0.30.4 smartinspectPython>=3.0.33 -spotifywebapiPython>=1.0.122 +spotifywebapiPython>=1.0.123