queue_id: str
queue_item_id: str
-
name: str
duration: int | None
sort_index: int = 0
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,
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
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",
# 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}")