fix embedded images
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 9 Mar 2023 18:51:15 +0000 (19:51 +0100)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 9 Mar 2023 18:51:15 +0000 (19:51 +0100)
music_assistant/server/controllers/metadata.py
music_assistant/server/helpers/images.py
music_assistant/server/helpers/tags.py

index 120db676e4d63889d273cde6e42f301345612fa4..abbcb2bfeed6e60be34baf2652630b9febc75fbd 100755 (executable)
@@ -4,6 +4,7 @@ from __future__ import annotations
 import asyncio
 import logging
 import os
+import urllib.parse
 from base64 import b64encode
 from random import shuffle
 from time import time
@@ -12,12 +13,7 @@ from typing import TYPE_CHECKING
 import aiofiles
 from aiohttp import web
 
-from music_assistant.common.models.enums import (
-    ImageType,
-    MediaType,
-    ProviderFeature,
-    ProviderType,
-)
+from music_assistant.common.models.enums import ImageType, MediaType, ProviderFeature, ProviderType
 from music_assistant.common.models.media_items import (
     Album,
     Artist,
@@ -310,7 +306,15 @@ class MetaDataController:
         """Handle request for image proxy."""
         path = request.query["path"]
         size = int(request.query.get("size", "0"))
-        image_data = await self.get_thumbnail(path, size)
+        if "%" in path:
+            # assume (double) encoded url, decode it
+            path = urllib.parse.unquote(path)
+
+        try:
+            image_data = await self.get_thumbnail(path, size)
+        except Exception as err:
+            LOGGER.exception(str(err), exc_info=err)
+
         # we set the cache header to 1 year (forever)
         # the client can use the checksum value to refresh when content changes
         return web.Response(
index 5781436353d874b1c5c48cc7d274d08673624d1b..79279551cb7b6676da99e4908e5d494e755e16d7 100644 (file)
@@ -27,8 +27,7 @@ async def get_image_data(mass: MusicAssistant, path: str) -> bytes:
             continue
         if not await prov.exists(path):
             continue
-        path = await prov.resolve(path)
-        img_data = await get_embedded_image(path.local_path)
+        img_data = await get_embedded_image(prov.read_file_content(path))
         if img_data:
             return img_data
     raise FileNotFoundError(f"Image not found: {path}")
index ec1f731fd2a88ee0c3ae3f17f01a91078a8959c3..0081a7dd8dcbbdb7e44771cddf919dc2a99ec871 100644 (file)
@@ -233,6 +233,7 @@ async def parse_tags(input_file: str | AsyncGenerator[bytes, None]) -> AudioTags
                         await proc.write(chunk)
                     except BrokenPipeError:
                         break  # race-condition: read enough data for tags
+                proc.write_eof()
 
             proc.attach_task(chunk_feeder())
 
@@ -272,16 +273,21 @@ async def get_embedded_image(input_file: str | AsyncGenerator[bytes, None]) -> b
     async with AsyncProcess(
         args, enable_stdin=file_path == "-", enable_stdout=True, enable_stderr=False
     ) as proc:
-        if file_path == "-":
-            # feed the file contents to the process
-            async for chunk in input_file:
-                await proc.write(chunk)
-
         if file_path == "-":
             # feed the file contents to the process
             async def chunk_feeder():
+                bytes_written = 0
                 async for chunk in input_file:
-                    await proc.write(chunk)
+                    try:
+                        await proc.write(chunk)
+                    except BrokenPipeError:
+                        break  # race-condition: read enough data for tags
+
+                    # grabbing the first 5MB is enough to get the embedded image
+                    bytes_written += len(chunk)
+                    if bytes_written > (5 * 1024000):
+                        break
+                proc.write_eof()
 
             proc.attach_task(chunk_feeder())