"""All constants for Music Assistant."""
-__version__ = "0.0.82"
+__version__ = "0.0.83"
REQUIRED_PYTHON_VER = "3.7"
# configuration keys/attributes
def compare_artists(left_artists: List[Artist], right_artists: List[Artist]):
- """Compare two lists of artist and return True if a match was found."""
+ """Compare two lists of artist and return True if both lists match."""
+ matches = 0
for left_artist in left_artists:
for right_artist in right_artists:
if compare_strings(left_artist.name, right_artist.name):
- return True
- return False
+ matches += 1
+ return len(left_artists) == matches
def compare_albums(left_albums: List[Album], right_albums: List[Album]):
# album match OR near exact duration match
left_albums = left_track.albums or [left_track.album]
right_albums = right_track.albums or [right_track.album]
- if not (
+ if (
compare_albums(left_albums, right_albums)
- or abs(left_track.duration - right_track.duration) <= 3
- ):
- return False
- # 100% match, all criteria passed
- return True
+ and abs(left_track.duration - right_track.duration) < 3
+ ) or abs(left_track.duration - right_track.duration) < 1:
+ # 100% match, all criteria passed
+ return True
+ return False
from typing import List, Optional, Union
from music_assistant.constants import (
+ CONF_ENABLED,
CONF_POWER_CONTROL,
CONF_VOLUME_CONTROL,
EVENT_PLAYER_ADDED,
return
if player.player_id in self._player_states:
return await self.async_update_player(player)
- # set the mass object on the player
+ player_enabled = self.mass.config.get_player_config(player.player_id)[
+ CONF_ENABLED
+ ]
+ if not player_enabled:
+ # do not add the player to states if it's disabled/unavailable
+ return
+ # set the mass object on the player and call on_add function
player.mass = self.mass
+ await player.async_on_add()
# create playerstate and queue object
- self._player_states[player.player_id] = PlayerState(self.mass, player)
+ player_state = PlayerState(self.mass, player)
+ self._player_states[player.player_id] = player_state
+
self._player_queues[player.player_id] = PlayerQueue(self.mass, player.player_id)
# TODO: turn on player if it was previously turned on ?
LOGGER.info(
"""Call when player is periodically polled by the player manager (should_poll=True)."""
self.update_state()
+ async def async_on_add(self) -> None:
+ """Call when player is added to the player manager."""
+
async def async_on_remove(self) -> None:
"""Call when player is removed from the player manager."""
player = self.mass.players.get_player(player_id)
if not player:
player = ChromecastPlayer(self.mass, cast_info)
- # if player was already added, it player will take care of reconnects itself.
+ # if player was already added, the player will take care of reconnects itself.
self.mass.add_job(player.async_set_cast_info, cast_info)
self.mass.add_job(self.mass.players.async_add_player(player))
"""Return player specific config entries (if any)."""
return PLAYER_CONFIG_ENTRIES
- async def async_set_cast_info(self, cast_info: ChromecastInfo) -> None:
- """Set the cast information and set up the chromecast object."""
- self._cast_info = cast_info
+ async def async_on_add(self) -> None:
+ """Call when player is added to the player manager."""
# Only setup the chromecast once, changes will automatically be picked up.
if self._chromecast is not None:
return
pychromecast.get_chromecast_from_service,
(
self.services,
- cast_info.uuid,
- cast_info.model_name,
- cast_info.friendly_name,
+ self._cast_info.uuid,
+ self._cast_info.model_name,
+ self._cast_info.friendly_name,
None,
None,
),
chromecast.mz_controller = mz_controller
self._chromecast.start()
+ async def async_set_cast_info(self, cast_info: ChromecastInfo) -> None:
+ """Set (or update) the cast discovery info."""
+ self._cast_info = cast_info
+
async def async_disconnect(self):
"""Disconnect Chromecast object if it is set."""
if self._chromecast is None: