Skip to content

Commit

Permalink
Fix: use relative path for all default images and collages
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelveldt committed Nov 3, 2024
1 parent e0d6015 commit fdc942f
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 33 deletions.
2 changes: 1 addition & 1 deletion music_assistant/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@


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"))
Expand Down
38 changes: 23 additions & 15 deletions music_assistant/controllers/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,18 @@ async def setup(self, config: CoreConfig) -> None:
# 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."""
Expand Down Expand Up @@ -353,6 +365,9 @@ async def get_thumbnail(
"""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
)
Expand Down Expand Up @@ -391,7 +406,7 @@ async def handle_imageproxy(self, request: web.Request) -> web.Response:
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."""
Expand All @@ -409,12 +424,13 @@ async def create_collage_image(
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,
)
Expand Down Expand Up @@ -641,13 +657,9 @@ async def _update_playlist_metadata(
# 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:
Expand All @@ -656,13 +668,9 @@ async def _update_playlist_metadata(
# 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:
Expand Down
48 changes: 31 additions & 17 deletions music_assistant/providers/builtin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
)
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
Expand Down Expand Up @@ -84,14 +84,14 @@ class StoredItem(TypedDict):

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,
)
Expand Down Expand Up @@ -143,20 +143,21 @@ async def loaded_in_mass(self) -> None:
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:
Expand Down Expand Up @@ -508,6 +509,19 @@ async def parse_item(
)
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
Expand Down

0 comments on commit fdc942f

Please sign in to comment.