From 734dc5b99b705ed9ce6089d85ee72f4484836442 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Mon, 28 Oct 2024 10:22:58 +0100 Subject: [PATCH] Fix: Prevent redundant lookup of full media item in queue controller --- music_assistant/common/models/queue_item.py | 1 - music_assistant/server/controllers/music.py | 13 +++++++++++++ .../server/controllers/player_queues.py | 15 +++++++-------- music_assistant/server/helpers/audio.py | 17 ++++++++++++++--- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/music_assistant/common/models/queue_item.py b/music_assistant/common/models/queue_item.py index 716e2b1be..8290b3871 100644 --- a/music_assistant/common/models/queue_item.py +++ b/music_assistant/common/models/queue_item.py @@ -19,7 +19,6 @@ class QueueItem(DataClassDictMixin): queue_id: str queue_item_id: str - name: str duration: int | None sort_index: int = 0 diff --git a/music_assistant/server/controllers/music.py b/music_assistant/server/controllers/music.py index 59f6e2a94..1d1f0e293 100644 --- a/music_assistant/server/controllers/music.py +++ b/music_assistant/server/controllers/music.py @@ -478,6 +478,19 @@ async def get_item( provider_instance_id_or_domain=provider_instance_id_or_domain, ) + async def get_library_item_by_prov_id( + self, + media_type: MediaType, + item_id: str, + provider_instance_id_or_domain: str, + ) -> MediaItemType | None: + """Get single library music item by id and media type.""" + ctrl = self.get_controller(media_type) + return await ctrl.get_library_item_by_prov_id( + item_id=item_id, + provider_instance_id_or_domain=provider_instance_id_or_domain, + ) + @api_command("music/favorites/add_item") async def add_item_to_favorites( self, diff --git a/music_assistant/server/controllers/player_queues.py b/music_assistant/server/controllers/player_queues.py index 43eac03b2..68eb7941c 100644 --- a/music_assistant/server/controllers/player_queues.py +++ b/music_assistant/server/controllers/player_queues.py @@ -1119,9 +1119,13 @@ async def load_next_item( queue_item=queue_item, prefer_album_loudness=prefer_album_loudness, ) - # Preload the full MediaItem for the QueueItem, making sure to get the - # maximum quality of thumbs - if queue_item.media_item: + # Ensure we have at least an image for the queue item, + # so grab full item if needed. Note that for YTM this is always needed + # because it has poor thumbs by default (..sigh) + if queue_item.media_item and ( + not queue_item.media_item.image + or queue_item.media_item.provider.startswith("ytmusic") + ): queue_item.media_item = await self.mass.music.get_item_by_uri(queue_item.uri) # allow stripping silence from the begin/end of the track if crossfade is enabled # this will allow for (much) smoother crossfades @@ -1134,11 +1138,6 @@ async def load_next_item( except MediaNotFoundError: # No stream details found, skip this QueueItem self.logger.debug("Skipping unplayable item: %s", next_item) - # we need to set a fake streamdetails object on the item - # otherwise our flow mode logic will break which - # calculates where we are in the queue - playlog = queue_item.streamdetails.play_log if queue_item.streamdetails else [] - playlog.append(0.0) queue_item.streamdetails = StreamDetails( provider=queue_item.media_item.provider if queue_item.media_item else "unknown", item_id=queue_item.media_item.item_id if queue_item.media_item else "unknown", diff --git a/music_assistant/server/helpers/audio.py b/music_assistant/server/helpers/audio.py index 472f4d7c2..22dc1ef61 100644 --- a/music_assistant/server/helpers/audio.py +++ b/music_assistant/server/helpers/audio.py @@ -199,11 +199,22 @@ async def get_stream_details( # this makes sure that playback has priority over other requests that may be # happening in the background BYPASS_THROTTLER.set(True) - # always request the full item as there might be other qualities available - full_item = await mass.music.get_item_by_uri(queue_item.uri) + if not queue_item.media_item: + # this should not happen, but guard it just in case + assert queue_item.streamdetails, "streamdetails required for non-mediaitem queueitems" + return queue_item.streamdetails + # always request the full library item as there might be other qualities available + media_item = ( + await mass.music.get_library_item_by_prov_id( + queue_item.media_item.media_type, + queue_item.media_item.item_id, + queue_item.media_item.provider, + ) + or queue_item.media_item + ) # sort by quality and check track availability for prov_media in sorted( - full_item.provider_mappings, key=lambda x: x.quality or 0, reverse=True + media_item.provider_mappings, key=lambda x: x.quality or 0, reverse=True ): if not prov_media.available: LOGGER.debug(f"Skipping unavailable {prov_media}")