From: Marcel van der Veldt Date: Sun, 3 Nov 2024 22:53:18 +0000 (+0100) Subject: Fix: use relative path for all default images and collages X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=fdc942fa3e853f5cd9c47ca42b3c1fe28ee623e6;p=music-assistant-server.git Fix: use relative path for all default images and collages --- diff --git a/music_assistant/constants.py b/music_assistant/constants.py index 57e53c01..381871b4 100644 --- a/music_assistant/constants.py +++ b/music_assistant/constants.py @@ -18,7 +18,7 @@ VARIOUS_ARTISTS_MBID: Final[str] = "89ad4ac3-39f7-470e-963a-56509c546377" RESOURCES_DIR: Final[pathlib.Path] = ( - pathlib.Path(__file__).parent.resolve().joinpath("server/helpers/resources") + pathlib.Path(__file__).parent.resolve().joinpath("helpers/resources") ) ANNOUNCE_ALERT_FILE: Final[str] = str(RESOURCES_DIR.joinpath("announce.mp3")) diff --git a/music_assistant/controllers/metadata.py b/music_assistant/controllers/metadata.py index 1aadabe9..cfa1e4c2 100644 --- a/music_assistant/controllers/metadata.py +++ b/music_assistant/controllers/metadata.py @@ -181,6 +181,18 @@ class MetaDataController(CoreController): # just tun the scan for missing metadata once at startup # TODO: allows to enable/disable this in the UI and configure interval/time self._missing_metadata_scan_task = self.mass.create_task(self._scan_missing_metadata()) + # migrate old image path for collage images from absolute to relative + # TODO: remove this after 2.5+ release + old_path = f"{self.mass.storage_path}/collage_images/" + new_path = "/collage/" + query = ( + "UPDATE playlists SET metadata = " + f"REPLACE (metadata, '{old_path}', '{new_path}') " + f"WHERE playlists.metadata LIKE '%{old_path}%'" + ) + if self.mass.music.database: + await self.mass.music.database.execute(query) + await self.mass.music.database.commit() async def close(self) -> None: """Handle logic on server stop.""" @@ -353,6 +365,9 @@ class MetaDataController(CoreController): """Get/create thumbnail image for path (image url or local path).""" if not self.mass.get_provider(provider) and not path.startswith("http"): raise ProviderUnavailableError + if provider == "builtin" and path.startswith("/collage/"): + # special case for collage images + path = os.path.join(self._collage_images_dir, path.split("/collage/")[-1]) thumbnail = await get_image_thumb( self.mass, path, size=size, provider=provider, image_format=image_format ) @@ -391,7 +406,7 @@ class MetaDataController(CoreController): async def create_collage_image( self, images: list[MediaItemImage], - img_path: str, + filename: str, fanart: bool = False, ) -> MediaItemImage | None: """Create collage thumb/fanart image for (in-library) playlist.""" @@ -409,12 +424,13 @@ class MetaDataController(CoreController): dimensions = (2500, 1750) if fanart else (1500, 1500) img_data = await create_collage(self.mass, images, dimensions) # always overwrite existing path - async with aiofiles.open(img_path, "wb") as _file: + file_path = os.path.join(self._collage_images_dir, filename) + async with aiofiles.open(file_path, "wb") as _file: await _file.write(img_data) del img_data return MediaItemImage( type=ImageType.FANART if fanart else ImageType.THUMB, - path=img_path, + path=f"/collage/{filename}", provider="builtin", remotely_accessible=False, ) @@ -641,13 +657,9 @@ class MetaDataController(CoreController): # thumb image thumb_image = next((x for x in cur_images if x.type == ImageType.THUMB), None) if not thumb_image or self._collage_images_dir in thumb_image.path: - thumb_image_path = ( - thumb_image.path - if thumb_image - else os.path.join(self._collage_images_dir, f"{uuid4().hex}_thumb.jpg") - ) + img_filename = thumb_image.path if thumb_image else f"{uuid4().hex}_thumb.jpg" if collage_thumb_image := await self.create_collage_image( - all_playlist_tracks_images, thumb_image_path + all_playlist_tracks_images, img_filename ): new_images.append(collage_thumb_image) elif thumb_image: @@ -656,13 +668,9 @@ class MetaDataController(CoreController): # fanart image fanart_image = next((x for x in cur_images if x.type == ImageType.FANART), None) if not fanart_image or self._collage_images_dir in fanart_image.path: - fanart_image_path = ( - fanart_image.path - if fanart_image - else os.path.join(self._collage_images_dir, f"{uuid4().hex}_fanart.jpg") - ) + img_filename = thumb_image.path if thumb_image else f"{uuid4().hex}_fanart.jpg" if collage_fanart_image := await self.create_collage_image( - all_playlist_tracks_images, fanart_image_path, fanart=True + all_playlist_tracks_images, img_filename, fanart=True ): new_images.append(collage_fanart_image) elif fanart_image: diff --git a/music_assistant/providers/builtin/__init__.py b/music_assistant/providers/builtin/__init__.py index 504cd107..6872d751 100644 --- a/music_assistant/providers/builtin/__init__.py +++ b/music_assistant/providers/builtin/__init__.py @@ -39,7 +39,7 @@ from music_assistant_models.media_items import ( ) from music_assistant_models.streamdetails import StreamDetails -from music_assistant.constants import MASS_LOGO, RESOURCES_DIR, VARIOUS_ARTISTS_FANART +from music_assistant.constants import MASS_LOGO, VARIOUS_ARTISTS_FANART from music_assistant.helpers.tags import AudioTags, parse_tags from music_assistant.helpers.uri import parse_uri from music_assistant.models.music_provider import MusicProvider @@ -84,14 +84,14 @@ COLLAGE_IMAGE_PLAYLISTS = (ALL_FAVORITE_TRACKS, RANDOM_TRACKS) DEFAULT_THUMB = MediaItemImage( type=ImageType.THUMB, - path=MASS_LOGO, + path="logo.png", provider="builtin", remotely_accessible=False, ) DEFAULT_FANART = MediaItemImage( type=ImageType.FANART, - path=VARIOUS_ARTISTS_FANART, + path="fanart.jpg", provider="builtin", remotely_accessible=False, ) @@ -143,20 +143,21 @@ class BuiltinProvider(MusicProvider): if not await asyncio.to_thread(os.path.exists, self._playlists_dir): await asyncio.to_thread(os.mkdir, self._playlists_dir) await super().loaded_in_mass() - # migrate old image path - # TODO: remove this after 2.3+ release - old_path = ( - "/usr/local/lib/python3.12/site-packages/music_assistant/server/helpers/resources" - ) - new_path = str(RESOURCES_DIR) - query = ( - "UPDATE playlists SET metadata = " - f"REPLACE (metadata, '{old_path}', '{new_path}') " - f"WHERE playlists.metadata LIKE '%{old_path}%'" - ) - if self.mass.music.database: - await self.mass.music.database.execute(query) - await self.mass.music.database.commit() + # migrate old image path from absolute to relative + # TODO: remove this after 2.5+ release + for old_path in ( + "/usr/local/lib/python3.12/site-packages/music_assistant/server/helpers/resources/", + "/app/venv/lib/python3.12/site-packages/music_assistant/server/helpers/resources/", + "/Users/marcelvanderveldt/Workdir/music-assistant/core/music_assistant/server/helpers/resources/", + ): + query = ( + "UPDATE playlists SET metadata = " + f"REPLACE (metadata, '{old_path}', '') " + f"WHERE playlists.metadata LIKE '%{old_path}%'" + ) + if self.mass.music.database: + await self.mass.music.database.execute(query) + await self.mass.music.database.commit() @property def is_streaming_provider(self) -> bool: @@ -508,6 +509,19 @@ class BuiltinProvider(MusicProvider): ) return media_item + async def resolve_image(self, path: str) -> str | bytes: + """ + Resolve an image from an image path. + + This either returns (a generator to get) raw bytes of the image or + a string with an http(s) URL or local path that is accessible from the server. + """ + if path == "logo.png": + return MASS_LOGO + if path in ("fanart.jpg", "fallback_fanart.jpeg"): + return VARIOUS_ARTISTS_FANART + return path + async def _get_media_info(self, url: str, force_refresh: bool = False) -> AudioTags: """Retrieve mediainfo for url.""" cache_category = CacheCategory.MEDIA_INFO