From: Marcel van der Veldt Date: Thu, 13 Jun 2024 22:14:34 +0000 (+0200) Subject: more fixes for playback and enqueuing X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=cc71ae4d7033622219964fe9247281382cb1089b;p=music-assistant-server.git more fixes for playback and enqueuing --- diff --git a/music_assistant/common/models/player_queue.py b/music_assistant/common/models/player_queue.py index 45176099..d205ce43 100644 --- a/music_assistant/common/models/player_queue.py +++ b/music_assistant/common/models/player_queue.py @@ -40,6 +40,7 @@ class PlayerQueue(DataClassDictMixin): # flow_mode_start_index: index of the first item of the flow stream flow_mode_start_index: int = 0 stream_finished: bool | None = None + end_of_track_reached: bool | None = None @property def corrected_elapsed_time(self) -> float: diff --git a/music_assistant/server/controllers/player_queues.py b/music_assistant/server/controllers/player_queues.py index 76e953f0..09627265 100644 --- a/music_assistant/server/controllers/player_queues.py +++ b/music_assistant/server/controllers/player_queues.py @@ -521,6 +521,7 @@ class PlayerQueuesController(CoreController): queue = self._queues[queue_id] queue.radio_source = [] queue.stream_finished = None + queue.end_of_track_reached = None if queue.state != PlayerState.IDLE: self.mass.create_task(self.stop(queue_id)) queue.current_index = None @@ -538,6 +539,7 @@ class PlayerQueuesController(CoreController): """ if queue := self.get(queue_id): queue.stream_finished = None + queue.end_of_track_reached = None # forward the actual stop command to the player provider if player_provider := self.mass.players.get_player_provider(queue_id): await player_provider.cmd_stop(queue_id) @@ -719,6 +721,7 @@ class PlayerQueuesController(CoreController): next_index = self._get_next_index(queue_id, index, allow_repeat=False) queue.flow_mode = player_needs_flow_mode and next_index is not None queue.stream_finished = False + queue.end_of_track_reached = False # get streamdetails - do this here to catch unavailable items early queue_item.streamdetails = await get_stream_details( self.mass, queue_item, seek_position=seek_position, fade_in=fade_in @@ -848,6 +851,16 @@ class PlayerQueuesController(CoreController): # return early if nothing changed if len(changed_keys) == 0: return + # check if we've reached the end of (the current) track + if ( + queue.current_item + and (duration := queue.current_item.duration) + and (duration - queue.elapsed_time) < 10 + ): + queue.end_of_track_reached = True + elif prev_state["current_index"] != new_state["current_index"]: + queue.end_of_track_reached = False + # handle enqueuing of next item to play if not queue.flow_mode or queue.stream_finished: self._check_enqueue_next(player, queue, prev_state, new_state) @@ -1164,7 +1177,10 @@ class PlayerQueuesController(CoreController): # we wait for the player to stop after it reaches the end of the track if ( (not queue.flow_mode or queue.repeat_mode == RepeatMode.ALL) + # we have a couple of guards here to prevent the player starting + # playback again when its stopped outside of MA's control and queue.stream_finished + and queue.end_of_track_reached and queue.state == PlayerState.IDLE ): queue.stream_finished = None diff --git a/music_assistant/server/providers/hass_players/__init__.py b/music_assistant/server/providers/hass_players/__init__.py index 1fd7275d..40fd0f4b 100644 --- a/music_assistant/server/providers/hass_players/__init__.py +++ b/music_assistant/server/providers/hass_players/__init__.py @@ -34,9 +34,10 @@ from music_assistant.server.providers.hass import DOMAIN as HASS_DOMAIN if TYPE_CHECKING: from collections.abc import AsyncGenerator - from hass_client.models import CompressedState, EntityStateEvent + from hass_client.models import CompressedState from hass_client.models import Device as HassDevice from hass_client.models import Entity as HassEntity + from hass_client.models import EntityStateEvent from hass_client.models import State as HassState from music_assistant.common.models.config_entries import ProviderConfig @@ -88,6 +89,10 @@ class MediaPlayerEntityFeature(IntFlag): CONF_ENFORCE_MP3 = "enforce_mp3" +CONF_ENTRY_ENFORCE_MP3_DEFAULT_ENABLED = ConfigEntry.from_dict( + {**CONF_ENTRY_ENFORCE_MP3.to_dict(), "default_value": True} +) + PLAYER_CONFIG_ENTRIES = ( CONF_ENTRY_CROSSFADE_FLOW_MODE_REQUIRED, CONF_ENTRY_CROSSFADE_DURATION, @@ -233,6 +238,18 @@ class HomeAssistantPlayers(PlayerProvider): "media_content_id": media.uri, "media_content_type": "music", "enqueue": "replace", + "extra": { + "metadata": { + "title": media.title, + "artist": media.artist, + "metadataType": 3, + "album": media.album, + "albumName": media.album, + "duration": media.duration, + "images": [{"url": media.image_url}] if media.image_url else None, + "imageUrl": media.image_url, + } + }, }, target={"entity_id": player_id}, ) @@ -338,6 +355,7 @@ class HomeAssistantPlayers(PlayerProvider): entity_id for entity_id, entity in entity_registry.items() if entity["platform"] == entity_registry_entry["platform"] + and state["entity_id"].startswith("media_player") and entity_id != state["entity_id"] ] hass_device = device_registry.get(entity_registry_entry["device_id"])