Skip to content

Commit

Permalink
[ 1.0.15 ] * Added MediaPlayerEntityFeature.VOLUME_MUTE support to …
Browse files Browse the repository at this point in the history
…handle volume mute requests.

  * Added `MediaPlayerEntityFeature.VOLUME_STEP` support to handle volume step requests.
  * Updated Media Browser logic to return an empty `BrowseMedia` object when ignoring Sonos-Card 'favorites' node requests, as a null object was causing numerous `Browse Media should use new BrowseMedia class` log warnings.
  * Updated underlying `spotifywebapiPython` package requirement to version 1.0.42.
  • Loading branch information
thlucas1 committed Apr 5, 2024
1 parent ff68d12 commit 5e25dbf
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 17 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ Change are listed in reverse chronological order (newest to oldest).

<span class="changelog">

###### [ 1.0.14 ] - 2024/04/01
###### [ 1.0.15 ] - 2024/04/05

* Added `MediaPlayerEntityFeature.VOLUME_MUTE` support to handle volume mute requests.
* Added `MediaPlayerEntityFeature.VOLUME_STEP` support to handle volume step requests.
* Updated Media Browser logic to return an empty `BrowseMedia` object when ignoring Sonos-Card 'favorites' node requests, as a null object was causing numerous `Browse Media should use new BrowseMedia class` log warnings.
* Updated underlying `spotifywebapiPython` package requirement to version 1.0.42.

###### [ 1.0.14 ] - 2024/04/04

* Added service `player_media_play_track_favorites` to play all track favorites for the current user.
* Increased all browse media limits from 50 items to 150 items.
Expand Down
4 changes: 2 additions & 2 deletions custom_components/spotifyplus/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"issue_tracker": "https://github.com/thlucas1/homeassistantcomponent_spotifyplus/issues",
"requirements": [
"smartinspectPython==3.0.33",
"spotifywebapiPython==1.0.41",
"spotifywebapiPython==1.0.42",
"urllib3>=1.21.1,<1.27"
],
"version": "1.0.14",
"version": "1.0.15",
"zeroconf": [ "_spotify-connect._tcp.local." ]
}
72 changes: 60 additions & 12 deletions custom_components/spotifyplus/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ def __init__(self, data:InstanceDataSpotifyPlus) -> None:
self._commandScanInterval:int = 0
self._lastKnownTimeRemainingSeconds:int = 0
self._isInCommandEvent:bool = False
self._volume_level_saved:float = None

# initialize base class attributes (MediaPlayerEntity).
self._attr_icon = "mdi:spotify"
Expand Down Expand Up @@ -304,7 +305,9 @@ def __init__(self, data:InstanceDataSpotifyPlus) -> None:
| MediaPlayerEntityFeature.SHUFFLE_SET \
| MediaPlayerEntityFeature.TURN_OFF \
| MediaPlayerEntityFeature.TURN_ON \
| MediaPlayerEntityFeature.VOLUME_SET
| MediaPlayerEntityFeature.VOLUME_MUTE \
| MediaPlayerEntityFeature.VOLUME_SET \
| MediaPlayerEntityFeature.VOLUME_STEP
else:
_logsi.LogVerbose("'%s': MediaPlayer is setting supported features for Spotify Non-Premium user" % self.name)
self._attr_supported_features = MediaPlayerEntityFeature.BROWSE_MEDIA
Expand Down Expand Up @@ -336,12 +339,6 @@ def state(self) -> MediaPlayerState:
return self._attr_state


@property
def volume_level(self) -> float | None:
""" Volume level of the media player (0.0 to 1.0). """
return self._attr_volume_level


@property
def media_content_id(self) -> str | None:
""" Return the media URL. """
Expand Down Expand Up @@ -439,6 +436,18 @@ def shuffle(self) -> bool | None:
def repeat(self) -> RepeatMode | str | None:
""" Return current repeat mode. """
return self._attr_repeat


@property
def volume_level(self) -> float | None:
""" Volume level of the media player (0.0 to 1.0). """
return self._attr_volume_level


@property
def is_volume_muted(self):
""" Boolean if volume is currently muted. """
return self._attr_is_volume_muted


@spotify_exception_handler
Expand Down Expand Up @@ -497,13 +506,34 @@ def media_seek(self, position: float) -> None:
# update ha state.
self._attr_media_position = position
self._attr_media_position_updated_at = utcnow()
self.async_schedule_update_ha_state()
self.async_write_ha_state()

# seek to track position.
deviceId:str = self._VerifyDeviceIdByName()
self.data.spotifyClient.PlayerMediaSeek(int(position * 1000), deviceId)


@spotify_exception_handler
def mute_volume(self, mute:bool) -> None:
""" Send mute command. """
_logsi.LogVerbose(STAppMessages.MSG_MEDIAPLAYER_SERVICE_WITH_PARMS, self.name, "mute_volume", "mute='%s'" % (mute))

self._attr_is_volume_muted = mute

if mute:
self._volume_level_saved = self._attr_volume_level
self.async_write_ha_state()
self.set_volume_level(0.0)
else:
# did we save the volume on a previous mute request? if not, then default volume.
if self._volume_level_saved is None or self._volume_level_saved == 0.0:
_logsi.LogVerbose("Previously saved volume was not set; defaulting to 0.10")
self._volume_level_saved = 0.10
self._attr_volume_level = self._volume_level_saved
self.async_write_ha_state()
self.set_volume_level(self._volume_level_saved)


@spotify_exception_handler
def play_media(self, media_type: MediaType | str, media_id: str, **kwargs: Any) -> None:
"""
Expand Down Expand Up @@ -609,7 +639,7 @@ def set_shuffle(self, shuffle: bool) -> None:

# update ha state.
self._attr_shuffle = shuffle
self.async_schedule_update_ha_state()
self.async_write_ha_state()

# set shuffle mode.
deviceId:str = self._VerifyDeviceIdByName()
Expand All @@ -625,7 +655,7 @@ def set_repeat(self, repeat: RepeatMode) -> None:
if repeat not in REPEAT_MODE_MAPPING_TO_SPOTIFY:
raise ValueError(f"Unsupported repeat mode: {repeat}")
self._attr_repeat = repeat
self.async_schedule_update_ha_state()
self.async_write_ha_state()

# set repeat mode.
deviceId:str = self._VerifyDeviceIdByName()
Expand All @@ -636,6 +666,10 @@ def set_repeat(self, repeat: RepeatMode) -> None:
def set_volume_level(self, volume: float) -> None:
""" Set the volume level. """
_logsi.LogVerbose(STAppMessages.MSG_MEDIAPLAYER_SERVICE_WITH_PARMS, self.name, "set_volume_level", "volume='%s'" % (volume))

# validations.
if volume is None:
volume = 0.0

# update ha state.
self._attr_volume_level = volume
Expand Down Expand Up @@ -910,7 +944,8 @@ def _UpdateHAFromPlayerPlayState(self, playerPlayState:PlayerPlayState) -> None:
self._attr_shuffle = None
self._attr_source = None
self._attr_volume_level = None

self._attr_is_volume_muted = None

# does player state exist? if not, then we are done.
if playerPlayState is None:
_logsi.LogVerbose("'%s': Spotify PlayerPlayState object was not set; nothing to do" % self.name)
Expand All @@ -928,6 +963,7 @@ def _UpdateHAFromPlayerPlayState(self, playerPlayState:PlayerPlayState) -> None:
self._attr_state = MediaPlayerState.IDLE
_logsi.LogVerbose("'%s': MediaPlayerState set to '%s'" % (self.name, self._attr_state))

self._attr_is_volume_muted = playerPlayState.IsMuted
self._attr_shuffle = playerPlayState.ShuffleState

# update item-related attributes (e.g. track? episode? etc)?
Expand Down Expand Up @@ -4289,7 +4325,19 @@ async def async_browse_media(
elif media_content_type == 'favorites':
# ignore Sonos-Card "favorites" node queries.
_logsi.LogVerbose("'%s': ignoring Sonos-Card favorites query (no SoundTouch equivalent)" % self.name)
return None

# Sonos-Card requires a valid BrowseMedia object, so return an empty one.
browseMedia:BrowseMedia = BrowseMedia(
can_expand=False,
can_play=False,
children=[],
children_media_class=None,
media_class=None,
media_content_id=media_content_id,
media_content_type=media_content_type,
title="Favorites not supported",
)
return browseMedia

else:

Expand Down
2 changes: 1 addition & 1 deletion custom_components/spotifyplus/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,7 @@ player_media_play_track_favorites:
name: Delay
description: Time delay (in seconds) to wait AFTER issuing the command to the player. This delay will give the spotify web api time to process the change before another command is issued. Default is 0.50; value range is 0 - 10.
example: "0.50"
required: true
required: false
selector:
text:

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ colorlog==6.7.0
homeassistant==2023.10.5
ruff==0.1.3
smartinspectPython>=3.0.33
spotifywebapiPython==1.0.41
spotifywebapiPython==1.0.42

0 comments on commit 5e25dbf

Please sign in to comment.